diff options
11 files changed, 751 insertions, 170 deletions
| diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt index be6e17e65..a6251bafd 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt @@ -112,25 +112,36 @@ class Settings {          const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown" -        const val PREF_OVERLAY_INIT = "OverlayInit" +        const val PREF_OVERLAY_VERSION = "OverlayVersion" +        const val PREF_LANDSCAPE_OVERLAY_VERSION = "LandscapeOverlayVersion" +        const val PREF_PORTRAIT_OVERLAY_VERSION = "PortraitOverlayVersion" +        const val PREF_FOLDABLE_OVERLAY_VERSION = "FoldableOverlayVersion" +        val overlayLayoutPrefs = listOf( +            PREF_LANDSCAPE_OVERLAY_VERSION, +            PREF_PORTRAIT_OVERLAY_VERSION, +            PREF_FOLDABLE_OVERLAY_VERSION +        ) +          const val PREF_CONTROL_SCALE = "controlScale"          const val PREF_CONTROL_OPACITY = "controlOpacity"          const val PREF_TOUCH_ENABLED = "isTouchEnabled" -        const val PREF_BUTTON_TOGGLE_0 = "buttonToggle0" -        const val PREF_BUTTON_TOGGLE_1 = "buttonToggle1" -        const val PREF_BUTTON_TOGGLE_2 = "buttonToggle2" -        const val PREF_BUTTON_TOGGLE_3 = "buttonToggle3" -        const val PREF_BUTTON_TOGGLE_4 = "buttonToggle4" -        const val PREF_BUTTON_TOGGLE_5 = "buttonToggle5" -        const val PREF_BUTTON_TOGGLE_6 = "buttonToggle6" -        const val PREF_BUTTON_TOGGLE_7 = "buttonToggle7" -        const val PREF_BUTTON_TOGGLE_8 = "buttonToggle8" -        const val PREF_BUTTON_TOGGLE_9 = "buttonToggle9" -        const val PREF_BUTTON_TOGGLE_10 = "buttonToggle10" -        const val PREF_BUTTON_TOGGLE_11 = "buttonToggle11" -        const val PREF_BUTTON_TOGGLE_12 = "buttonToggle12" -        const val PREF_BUTTON_TOGGLE_13 = "buttonToggle13" -        const val PREF_BUTTON_TOGGLE_14 = "buttonToggle14" +        const val PREF_BUTTON_A = "buttonToggle0" +        const val PREF_BUTTON_B = "buttonToggle1" +        const val PREF_BUTTON_X = "buttonToggle2" +        const val PREF_BUTTON_Y = "buttonToggle3" +        const val PREF_BUTTON_L = "buttonToggle4" +        const val PREF_BUTTON_R = "buttonToggle5" +        const val PREF_BUTTON_ZL = "buttonToggle6" +        const val PREF_BUTTON_ZR = "buttonToggle7" +        const val PREF_BUTTON_PLUS = "buttonToggle8" +        const val PREF_BUTTON_MINUS = "buttonToggle9" +        const val PREF_BUTTON_DPAD = "buttonToggle10" +        const val PREF_STICK_L = "buttonToggle11" +        const val PREF_STICK_R = "buttonToggle12" +        const val PREF_BUTTON_STICK_L = "buttonToggle13" +        const val PREF_BUTTON_STICK_R = "buttonToggle14" +        const val PREF_BUTTON_HOME = "buttonToggle15" +        const val PREF_BUTTON_SCREENSHOT = "buttonToggle16"          const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"          const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable" @@ -145,6 +156,30 @@ class Settings {          private val configFileSectionsMap: MutableMap<String, List<String>> = HashMap() +        val overlayPreferences = listOf( +            PREF_OVERLAY_VERSION, +            PREF_CONTROL_SCALE, +            PREF_CONTROL_OPACITY, +            PREF_TOUCH_ENABLED, +            PREF_BUTTON_A, +            PREF_BUTTON_B, +            PREF_BUTTON_X, +            PREF_BUTTON_Y, +            PREF_BUTTON_L, +            PREF_BUTTON_R, +            PREF_BUTTON_ZL, +            PREF_BUTTON_ZR, +            PREF_BUTTON_PLUS, +            PREF_BUTTON_MINUS, +            PREF_BUTTON_DPAD, +            PREF_STICK_L, +            PREF_STICK_R, +            PREF_BUTTON_HOME, +            PREF_BUTTON_SCREENSHOT, +            PREF_BUTTON_STICK_L, +            PREF_BUTTON_STICK_R +        ) +          const val LayoutOption_Unspecified = 0          const val LayoutOption_MobilePortrait = 4          const val LayoutOption_MobileLandscape = 5 diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index 09976db62..0e7c1ba88 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -212,9 +212,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {              }              if (!isInFoldableLayout) {                  if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { -                    binding.surfaceInputOverlay.orientation = InputOverlay.PORTRAIT +                    binding.surfaceInputOverlay.layout = InputOverlay.PORTRAIT                  } else { -                    binding.surfaceInputOverlay.orientation = InputOverlay.LANDSCAPE +                    binding.surfaceInputOverlay.layout = InputOverlay.LANDSCAPE                  }              }              if (!binding.surfaceInputOverlay.isInEditMode) { @@ -260,7 +260,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {              .remove(Settings.PREF_CONTROL_SCALE)              .remove(Settings.PREF_CONTROL_OPACITY)              .apply() -        binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.resetButtonPlacement() } +        binding.surfaceInputOverlay.post { +            binding.surfaceInputOverlay.resetLayoutVisibilityAndPlacement() +        }      }      private fun updateShowFpsOverlay() { @@ -337,7 +339,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {                          binding.inGameMenu.layoutParams.height = it.bounds.bottom                          isInFoldableLayout = true -                        binding.surfaceInputOverlay.orientation = InputOverlay.FOLDABLE +                        binding.surfaceInputOverlay.layout = InputOverlay.FOLDABLE                          refreshInputOverlay()                      }                  } @@ -410,9 +412,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {                  R.id.menu_toggle_controls -> {                      val preferences =                          PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) -                    val optionsArray = BooleanArray(15) -                    for (i in 0..14) { -                        optionsArray[i] = preferences.getBoolean("buttonToggle$i", i < 13) +                    val optionsArray = BooleanArray(Settings.overlayPreferences.size) +                    Settings.overlayPreferences.forEachIndexed { i, _ -> +                        optionsArray[i] = preferences.getBoolean("buttonToggle$i", i < 15)                      }                      val dialog = MaterialAlertDialogBuilder(requireContext()) @@ -436,7 +438,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {                      dialog.getButton(AlertDialog.BUTTON_NEUTRAL)                          .setOnClickListener {                              val isChecked = !optionsArray[0] -                            for (i in 0..14) { +                            Settings.overlayPreferences.forEachIndexed { i, _ ->                                  optionsArray[i] = isChecked                                  dialog.listView.setItemChecked(i, isChecked)                                  preferences.edit() diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt index 6251ec783..c055c2e35 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt @@ -51,15 +51,23 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :      private lateinit var windowInsets: WindowInsets -    var orientation = LANDSCAPE +    var layout = LANDSCAPE      override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {          super.onLayout(changed, left, top, right, bottom)          windowInsets = rootWindowInsets -        if (!preferences.getBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", false)) { -            defaultOverlay() +        val overlayVersion = preferences.getInt(Settings.PREF_OVERLAY_VERSION, 0) +        if (overlayVersion != OVERLAY_VERSION) { +            resetAllLayouts() +        } else { +            val layoutIndex = overlayLayouts.indexOf(layout) +            val currentLayoutVersion = +                preferences.getInt(Settings.overlayLayoutPrefs[layoutIndex], 0) +            if (currentLayoutVersion != overlayLayoutVersions[layoutIndex]) { +                resetCurrentLayout() +            }          }          // Load the controls. @@ -266,10 +274,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                  MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) {                      // Persist button position by saving new place.                      saveControlPosition( -                        buttonBeingConfigured!!.buttonId, +                        buttonBeingConfigured!!.prefId,                          buttonBeingConfigured!!.bounds.centerX(),                          buttonBeingConfigured!!.bounds.centerY(), -                        orientation +                        layout                      )                      buttonBeingConfigured = null                  } @@ -299,10 +307,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                  MotionEvent.ACTION_POINTER_UP -> if (dpadBeingConfigured === dpad) {                      // Persist button position by saving new place.                      saveControlPosition( -                        dpadBeingConfigured!!.upId, +                        Settings.PREF_BUTTON_DPAD,                          dpadBeingConfigured!!.bounds.centerX(),                          dpadBeingConfigured!!.bounds.centerY(), -                        orientation +                        layout                      )                      dpadBeingConfigured = null                  } @@ -330,10 +338,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                  MotionEvent.ACTION_UP,                  MotionEvent.ACTION_POINTER_UP -> if (joystickBeingConfigured != null) {                      saveControlPosition( -                        joystickBeingConfigured!!.buttonId, +                        joystickBeingConfigured!!.prefId,                          joystickBeingConfigured!!.bounds.centerX(),                          joystickBeingConfigured!!.bounds.centerY(), -                        orientation +                        layout                      )                      joystickBeingConfigured = null                  } @@ -343,9 +351,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :          return true      } -    private fun addOverlayControls(orientation: String) { +    private fun addOverlayControls(layout: String) {          val windowSize = getSafeScreenSize(context) -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_0, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_A, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -353,11 +361,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.facebutton_a,                      R.drawable.facebutton_a_depressed,                      ButtonType.BUTTON_A, -                    orientation +                    Settings.PREF_BUTTON_A, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_1, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_B, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -365,11 +374,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.facebutton_b,                      R.drawable.facebutton_b_depressed,                      ButtonType.BUTTON_B, -                    orientation +                    Settings.PREF_BUTTON_B, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_2, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_X, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -377,11 +387,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.facebutton_x,                      R.drawable.facebutton_x_depressed,                      ButtonType.BUTTON_X, -                    orientation +                    Settings.PREF_BUTTON_X, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_3, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_Y, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -389,11 +400,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.facebutton_y,                      R.drawable.facebutton_y_depressed,                      ButtonType.BUTTON_Y, -                    orientation +                    Settings.PREF_BUTTON_Y, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_4, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_L, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -401,11 +413,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.l_shoulder,                      R.drawable.l_shoulder_depressed,                      ButtonType.TRIGGER_L, -                    orientation +                    Settings.PREF_BUTTON_L, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_5, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_R, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -413,11 +426,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.r_shoulder,                      R.drawable.r_shoulder_depressed,                      ButtonType.TRIGGER_R, -                    orientation +                    Settings.PREF_BUTTON_R, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_6, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_ZL, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -425,11 +439,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.zl_trigger,                      R.drawable.zl_trigger_depressed,                      ButtonType.TRIGGER_ZL, -                    orientation +                    Settings.PREF_BUTTON_ZL, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_7, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_ZR, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -437,11 +452,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.zr_trigger,                      R.drawable.zr_trigger_depressed,                      ButtonType.TRIGGER_ZR, -                    orientation +                    Settings.PREF_BUTTON_ZR, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_8, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_PLUS, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -449,11 +465,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.facebutton_plus,                      R.drawable.facebutton_plus_depressed,                      ButtonType.BUTTON_PLUS, -                    orientation +                    Settings.PREF_BUTTON_PLUS, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_9, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_MINUS, true)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -461,11 +478,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.facebutton_minus,                      R.drawable.facebutton_minus_depressed,                      ButtonType.BUTTON_MINUS, -                    orientation +                    Settings.PREF_BUTTON_MINUS, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_10, true)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_DPAD, true)) {              overlayDpads.add(                  initializeOverlayDpad(                      context, @@ -473,11 +491,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.dpad_standard,                      R.drawable.dpad_standard_cardinal_depressed,                      R.drawable.dpad_standard_diagonal_depressed, -                    orientation +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_11, true)) { +        if (preferences.getBoolean(Settings.PREF_STICK_L, true)) {              overlayJoysticks.add(                  initializeOverlayJoystick(                      context, @@ -487,11 +505,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.joystick_depressed,                      StickType.STICK_L,                      ButtonType.STICK_L, -                    orientation +                    Settings.PREF_STICK_L, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_12, true)) { +        if (preferences.getBoolean(Settings.PREF_STICK_R, true)) {              overlayJoysticks.add(                  initializeOverlayJoystick(                      context, @@ -501,11 +520,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.joystick_depressed,                      StickType.STICK_R,                      ButtonType.STICK_R, -                    orientation +                    Settings.PREF_STICK_R, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_13, false)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_HOME, false)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -513,11 +533,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.facebutton_home,                      R.drawable.facebutton_home_depressed,                      ButtonType.BUTTON_HOME, -                    orientation +                    Settings.PREF_BUTTON_HOME, +                    layout                  )              )          } -        if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_14, false)) { +        if (preferences.getBoolean(Settings.PREF_BUTTON_SCREENSHOT, false)) {              overlayButtons.add(                  initializeOverlayButton(                      context, @@ -525,7 +546,34 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                      R.drawable.facebutton_screenshot,                      R.drawable.facebutton_screenshot_depressed,                      ButtonType.BUTTON_CAPTURE, -                    orientation +                    Settings.PREF_BUTTON_SCREENSHOT, +                    layout +                ) +            ) +        } +        if (preferences.getBoolean(Settings.PREF_BUTTON_STICK_L, true)) { +            overlayButtons.add( +                initializeOverlayButton( +                    context, +                    windowSize, +                    R.drawable.button_l3, +                    R.drawable.button_l3_depressed, +                    ButtonType.STICK_L, +                    Settings.PREF_BUTTON_STICK_L, +                    layout +                ) +            ) +        } +        if (preferences.getBoolean(Settings.PREF_BUTTON_STICK_R, true)) { +            overlayButtons.add( +                initializeOverlayButton( +                    context, +                    windowSize, +                    R.drawable.button_r3, +                    R.drawable.button_r3_depressed, +                    ButtonType.STICK_R, +                    Settings.PREF_BUTTON_STICK_R, +                    layout                  )              )          } @@ -539,18 +587,18 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :          // Add all the enabled overlay items back to the HashSet.          if (EmulationMenuSettings.showOverlay) { -            addOverlayControls(orientation) +            addOverlayControls(layout)          }          invalidate()      } -    private fun saveControlPosition(sharedPrefsId: Int, x: Int, y: Int, orientation: String) { +    private fun saveControlPosition(prefId: String, x: Int, y: Int, layout: String) {          val windowSize = getSafeScreenSize(context)          val min = windowSize.first          val max = windowSize.second          PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit() -            .putFloat("$sharedPrefsId-X$orientation", (x - min.x).toFloat() / max.x) -            .putFloat("$sharedPrefsId-Y$orientation", (y - min.y).toFloat() / max.y) +            .putFloat("$prefId-X$layout", (x - min.x).toFloat() / max.x) +            .putFloat("$prefId-Y$layout", (y - min.y).toFloat() / max.y)              .apply()      } @@ -558,19 +606,31 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :          inEditMode = editMode      } -    private fun defaultOverlay() { -        if (!preferences.getBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", false)) { -            defaultOverlayByLayout(orientation) -        } - -        resetButtonPlacement() +    private fun resetCurrentLayout() { +        defaultOverlayByLayout(layout) +        val layoutIndex = overlayLayouts.indexOf(layout)          preferences.edit() -            .putBoolean("${Settings.PREF_OVERLAY_INIT}$orientation", true) +            .putInt(Settings.overlayLayoutPrefs[layoutIndex], overlayLayoutVersions[layoutIndex])              .apply()      } -    fun resetButtonPlacement() { -        defaultOverlayByLayout(orientation) +    private fun resetAllLayouts() { +        val editor = preferences.edit() +        overlayLayouts.forEachIndexed { i, layout -> +            defaultOverlayByLayout(layout) +            editor.putInt(Settings.overlayLayoutPrefs[i], overlayLayoutVersions[i]) +        } +        editor.putInt(Settings.PREF_OVERLAY_VERSION, OVERLAY_VERSION) +        editor.apply() +    } + +    fun resetLayoutVisibilityAndPlacement() { +        defaultOverlayByLayout(layout) +        val editor = preferences.edit() +        Settings.overlayPreferences.forEachIndexed { _, pref -> +            editor.remove(pref) +        } +        editor.apply()          refreshControls()      } @@ -604,7 +664,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :          R.integer.SWITCH_STICK_R_X,          R.integer.SWITCH_STICK_R_Y,          R.integer.SWITCH_STICK_L_X, -        R.integer.SWITCH_STICK_L_Y +        R.integer.SWITCH_STICK_L_Y, +        R.integer.SWITCH_BUTTON_STICK_L_X, +        R.integer.SWITCH_BUTTON_STICK_L_Y, +        R.integer.SWITCH_BUTTON_STICK_R_X, +        R.integer.SWITCH_BUTTON_STICK_R_Y      )      private val portraitResources = arrayOf( @@ -637,7 +701,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :          R.integer.SWITCH_STICK_R_X_PORTRAIT,          R.integer.SWITCH_STICK_R_Y_PORTRAIT,          R.integer.SWITCH_STICK_L_X_PORTRAIT, -        R.integer.SWITCH_STICK_L_Y_PORTRAIT +        R.integer.SWITCH_STICK_L_Y_PORTRAIT, +        R.integer.SWITCH_BUTTON_STICK_L_X_PORTRAIT, +        R.integer.SWITCH_BUTTON_STICK_L_Y_PORTRAIT, +        R.integer.SWITCH_BUTTON_STICK_R_X_PORTRAIT, +        R.integer.SWITCH_BUTTON_STICK_R_Y_PORTRAIT      )      private val foldableResources = arrayOf( @@ -670,139 +738,159 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :          R.integer.SWITCH_STICK_R_X_FOLDABLE,          R.integer.SWITCH_STICK_R_Y_FOLDABLE,          R.integer.SWITCH_STICK_L_X_FOLDABLE, -        R.integer.SWITCH_STICK_L_Y_FOLDABLE +        R.integer.SWITCH_STICK_L_Y_FOLDABLE, +        R.integer.SWITCH_BUTTON_STICK_L_X_FOLDABLE, +        R.integer.SWITCH_BUTTON_STICK_L_Y_FOLDABLE, +        R.integer.SWITCH_BUTTON_STICK_R_X_FOLDABLE, +        R.integer.SWITCH_BUTTON_STICK_R_Y_FOLDABLE      ) -    private fun getResourceValue(orientation: String, position: Int): Float { -        return when (orientation) { +    private fun getResourceValue(layout: String, position: Int): Float { +        return when (layout) {              PORTRAIT -> resources.getInteger(portraitResources[position]).toFloat() / 1000              FOLDABLE -> resources.getInteger(foldableResources[position]).toFloat() / 1000              else -> resources.getInteger(landscapeResources[position]).toFloat() / 1000          }      } -    private fun defaultOverlayByLayout(orientation: String) { +    private fun defaultOverlayByLayout(layout: String) {          // Each value represents the position of the button in relation to the screen size without insets.          preferences.edit()              .putFloat( -                ButtonType.BUTTON_A.toString() + "-X$orientation", -                getResourceValue(orientation, 0) +                "${Settings.PREF_BUTTON_A}-X$layout", +                getResourceValue(layout, 0) +            ) +            .putFloat( +                "${Settings.PREF_BUTTON_A}-Y$layout", +                getResourceValue(layout, 1) +            ) +            .putFloat( +                "${Settings.PREF_BUTTON_B}-X$layout", +                getResourceValue(layout, 2) +            ) +            .putFloat( +                "${Settings.PREF_BUTTON_B}-Y$layout", +                getResourceValue(layout, 3) +            ) +            .putFloat( +                "${Settings.PREF_BUTTON_X}-X$layout", +                getResourceValue(layout, 4)              )              .putFloat( -                ButtonType.BUTTON_A.toString() + "-Y$orientation", -                getResourceValue(orientation, 1) +                "${Settings.PREF_BUTTON_X}-Y$layout", +                getResourceValue(layout, 5)              )              .putFloat( -                ButtonType.BUTTON_B.toString() + "-X$orientation", -                getResourceValue(orientation, 2) +                "${Settings.PREF_BUTTON_Y}-X$layout", +                getResourceValue(layout, 6)              )              .putFloat( -                ButtonType.BUTTON_B.toString() + "-Y$orientation", -                getResourceValue(orientation, 3) +                "${Settings.PREF_BUTTON_Y}-Y$layout", +                getResourceValue(layout, 7)              )              .putFloat( -                ButtonType.BUTTON_X.toString() + "-X$orientation", -                getResourceValue(orientation, 4) +                "${Settings.PREF_BUTTON_ZL}-X$layout", +                getResourceValue(layout, 8)              )              .putFloat( -                ButtonType.BUTTON_X.toString() + "-Y$orientation", -                getResourceValue(orientation, 5) +                "${Settings.PREF_BUTTON_ZL}-Y$layout", +                getResourceValue(layout, 9)              )              .putFloat( -                ButtonType.BUTTON_Y.toString() + "-X$orientation", -                getResourceValue(orientation, 6) +                "${Settings.PREF_BUTTON_ZR}-X$layout", +                getResourceValue(layout, 10)              )              .putFloat( -                ButtonType.BUTTON_Y.toString() + "-Y$orientation", -                getResourceValue(orientation, 7) +                "${Settings.PREF_BUTTON_ZR}-Y$layout", +                getResourceValue(layout, 11)              )              .putFloat( -                ButtonType.TRIGGER_ZL.toString() + "-X$orientation", -                getResourceValue(orientation, 8) +                "${Settings.PREF_BUTTON_DPAD}-X$layout", +                getResourceValue(layout, 12)              )              .putFloat( -                ButtonType.TRIGGER_ZL.toString() + "-Y$orientation", -                getResourceValue(orientation, 9) +                "${Settings.PREF_BUTTON_DPAD}-Y$layout", +                getResourceValue(layout, 13)              )              .putFloat( -                ButtonType.TRIGGER_ZR.toString() + "-X$orientation", -                getResourceValue(orientation, 10) +                "${Settings.PREF_BUTTON_L}-X$layout", +                getResourceValue(layout, 14)              )              .putFloat( -                ButtonType.TRIGGER_ZR.toString() + "-Y$orientation", -                getResourceValue(orientation, 11) +                "${Settings.PREF_BUTTON_L}-Y$layout", +                getResourceValue(layout, 15)              )              .putFloat( -                ButtonType.DPAD_UP.toString() + "-X$orientation", -                getResourceValue(orientation, 12) +                "${Settings.PREF_BUTTON_R}-X$layout", +                getResourceValue(layout, 16)              )              .putFloat( -                ButtonType.DPAD_UP.toString() + "-Y$orientation", -                getResourceValue(orientation, 13) +                "${Settings.PREF_BUTTON_R}-Y$layout", +                getResourceValue(layout, 17)              )              .putFloat( -                ButtonType.TRIGGER_L.toString() + "-X$orientation", -                getResourceValue(orientation, 14) +                "${Settings.PREF_BUTTON_PLUS}-X$layout", +                getResourceValue(layout, 18)              )              .putFloat( -                ButtonType.TRIGGER_L.toString() + "-Y$orientation", -                getResourceValue(orientation, 15) +                "${Settings.PREF_BUTTON_PLUS}-Y$layout", +                getResourceValue(layout, 19)              )              .putFloat( -                ButtonType.TRIGGER_R.toString() + "-X$orientation", -                getResourceValue(orientation, 16) +                "${Settings.PREF_BUTTON_MINUS}-X$layout", +                getResourceValue(layout, 20)              )              .putFloat( -                ButtonType.TRIGGER_R.toString() + "-Y$orientation", -                getResourceValue(orientation, 17) +                "${Settings.PREF_BUTTON_MINUS}-Y$layout", +                getResourceValue(layout, 21)              )              .putFloat( -                ButtonType.BUTTON_PLUS.toString() + "-X$orientation", -                getResourceValue(orientation, 18) +                "${Settings.PREF_BUTTON_HOME}-X$layout", +                getResourceValue(layout, 22)              )              .putFloat( -                ButtonType.BUTTON_PLUS.toString() + "-Y$orientation", -                getResourceValue(orientation, 19) +                "${Settings.PREF_BUTTON_HOME}-Y$layout", +                getResourceValue(layout, 23)              )              .putFloat( -                ButtonType.BUTTON_MINUS.toString() + "-X$orientation", -                getResourceValue(orientation, 20) +                "${Settings.PREF_BUTTON_SCREENSHOT}-X$layout", +                getResourceValue(layout, 24)              )              .putFloat( -                ButtonType.BUTTON_MINUS.toString() + "-Y$orientation", -                getResourceValue(orientation, 21) +                "${Settings.PREF_BUTTON_SCREENSHOT}-Y$layout", +                getResourceValue(layout, 25)              )              .putFloat( -                ButtonType.BUTTON_HOME.toString() + "-X$orientation", -                getResourceValue(orientation, 22) +                "${Settings.PREF_STICK_R}-X$layout", +                getResourceValue(layout, 26)              )              .putFloat( -                ButtonType.BUTTON_HOME.toString() + "-Y$orientation", -                getResourceValue(orientation, 23) +                "${Settings.PREF_STICK_R}-Y$layout", +                getResourceValue(layout, 27)              )              .putFloat( -                ButtonType.BUTTON_CAPTURE.toString() + "-X$orientation", -                getResourceValue(orientation, 24) +                "${Settings.PREF_STICK_L}-X$layout", +                getResourceValue(layout, 28)              )              .putFloat( -                ButtonType.BUTTON_CAPTURE.toString() + "-Y$orientation", -                getResourceValue(orientation, 25) +                "${Settings.PREF_STICK_L}-Y$layout", +                getResourceValue(layout, 29)              )              .putFloat( -                ButtonType.STICK_R.toString() + "-X$orientation", -                getResourceValue(orientation, 26) +                "${Settings.PREF_BUTTON_STICK_L}-X$layout", +                getResourceValue(layout, 30)              )              .putFloat( -                ButtonType.STICK_R.toString() + "-Y$orientation", -                getResourceValue(orientation, 27) +                "${Settings.PREF_BUTTON_STICK_L}-Y$layout", +                getResourceValue(layout, 31)              )              .putFloat( -                ButtonType.STICK_L.toString() + "-X$orientation", -                getResourceValue(orientation, 28) +                "${Settings.PREF_BUTTON_STICK_R}-X$layout", +                getResourceValue(layout, 32)              )              .putFloat( -                ButtonType.STICK_L.toString() + "-Y$orientation", -                getResourceValue(orientation, 29) +                "${Settings.PREF_BUTTON_STICK_R}-Y$layout", +                getResourceValue(layout, 33)              )              .apply()      } @@ -812,12 +900,30 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :      }      companion object { +        // Increase this number every time there is a breaking change to every overlay layout +        const val OVERLAY_VERSION = 1 + +        // Increase the corresponding layout version number whenever that layout has a breaking change +        private const val LANDSCAPE_OVERLAY_VERSION = 1 +        private const val PORTRAIT_OVERLAY_VERSION = 1 +        private const val FOLDABLE_OVERLAY_VERSION = 1 +        val overlayLayoutVersions = listOf( +            LANDSCAPE_OVERLAY_VERSION, +            PORTRAIT_OVERLAY_VERSION, +            FOLDABLE_OVERLAY_VERSION +        ) +          private val preferences: SharedPreferences =              PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) -        const val LANDSCAPE = "" +        const val LANDSCAPE = "_Landscape"          const val PORTRAIT = "_Portrait"          const val FOLDABLE = "_Foldable" +        val overlayLayouts = listOf( +            LANDSCAPE, +            PORTRAIT, +            FOLDABLE +        )          /**           * Resizes a [Bitmap] by a given scale factor @@ -948,6 +1054,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :           * @param defaultResId The resource ID of the [Drawable] to get the [Bitmap] of (Default State).           * @param pressedResId The resource ID of the [Drawable] to get the [Bitmap] of (Pressed State).           * @param buttonId     Identifier for determining what type of button the initialized InputOverlayDrawableButton represents. +         * @param prefId       Identifier for determining where a button appears on screen. +         * @param layout       The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE].           * @return An [InputOverlayDrawableButton] with the correct drawing bounds set.           */          private fun initializeOverlayButton( @@ -956,7 +1064,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :              defaultResId: Int,              pressedResId: Int,              buttonId: Int, -            orientation: String +            prefId: String, +            layout: String          ): InputOverlayDrawableButton {              // Resources handle for fetching the initial Drawable resource.              val res = context.resources @@ -964,17 +1073,20 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :              // SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableButton.              val sPrefs = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) -            // Decide scale based on button ID and user preference -            var scale: Float = when (buttonId) { -                ButtonType.BUTTON_HOME, -                ButtonType.BUTTON_CAPTURE, -                ButtonType.BUTTON_PLUS, -                ButtonType.BUTTON_MINUS -> 0.07f +            // Decide scale based on button preference ID and user preference +            var scale: Float = when (prefId) { +                Settings.PREF_BUTTON_HOME, +                Settings.PREF_BUTTON_SCREENSHOT, +                Settings.PREF_BUTTON_PLUS, +                Settings.PREF_BUTTON_MINUS -> 0.07f -                ButtonType.TRIGGER_L, -                ButtonType.TRIGGER_R, -                ButtonType.TRIGGER_ZL, -                ButtonType.TRIGGER_ZR -> 0.26f +                Settings.PREF_BUTTON_L, +                Settings.PREF_BUTTON_R, +                Settings.PREF_BUTTON_ZL, +                Settings.PREF_BUTTON_ZR -> 0.26f + +                Settings.PREF_BUTTON_STICK_L, +                Settings.PREF_BUTTON_STICK_R -> 0.155f                  else -> 0.11f              } @@ -984,8 +1096,13 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :              // Initialize the InputOverlayDrawableButton.              val defaultStateBitmap = getBitmap(context, defaultResId, scale)              val pressedStateBitmap = getBitmap(context, pressedResId, scale) -            val overlayDrawable = -                InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, buttonId) +            val overlayDrawable = InputOverlayDrawableButton( +                res, +                defaultStateBitmap, +                pressedStateBitmap, +                buttonId, +                prefId +            )              // Get the minimum and maximum coordinates of the screen where the button can be placed.              val min = windowSize.first @@ -993,8 +1110,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :              // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.              // These were set in the input overlay configuration menu. -            val xKey = "$buttonId-X$orientation" -            val yKey = "$buttonId-Y$orientation" +            val xKey = "$prefId-X$layout" +            val yKey = "$prefId-Y$layout"              val drawableXPercent = sPrefs.getFloat(xKey, 0f)              val drawableYPercent = sPrefs.getFloat(yKey, 0f)              val drawableX = (drawableXPercent * max.x + min.x).toInt() @@ -1029,7 +1146,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :           * @param defaultResId              The [Bitmap] resource ID of the default state.           * @param pressedOneDirectionResId  The [Bitmap] resource ID of the pressed state in one direction.           * @param pressedTwoDirectionsResId The [Bitmap] resource ID of the pressed state in two directions. -         * @return the initialized [InputOverlayDrawableDpad] +         * @param layout                    The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE]. +         * @return The initialized [InputOverlayDrawableDpad]           */          private fun initializeOverlayDpad(              context: Context, @@ -1037,7 +1155,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :              defaultResId: Int,              pressedOneDirectionResId: Int,              pressedTwoDirectionsResId: Int, -            orientation: String +            layout: String          ): InputOverlayDrawableDpad {              // Resources handle for fetching the initial Drawable resource.              val res = context.resources @@ -1074,8 +1192,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :              // The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay.              // These were set in the input overlay configuration menu. -            val drawableXPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-X$orientation", 0f) -            val drawableYPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-Y$orientation", 0f) +            val drawableXPercent = sPrefs.getFloat("${Settings.PREF_BUTTON_DPAD}-X$layout", 0f) +            val drawableYPercent = sPrefs.getFloat("${Settings.PREF_BUTTON_DPAD}-Y$layout", 0f)              val drawableX = (drawableXPercent * max.x + min.x).toInt()              val drawableY = (drawableYPercent * max.y + min.y).toInt()              val width = overlayDrawable.width @@ -1107,7 +1225,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :           * @param pressedResInner Resource ID for the pressed inner image of the joystick.           * @param joystick        Identifier for which joystick this is.           * @param button          Identifier for which joystick button this is. -         * @return the initialized [InputOverlayDrawableJoystick]. +         * @param prefId          Identifier for determining where a button appears on screen. +         * @param layout          The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE]. +         * @return The initialized [InputOverlayDrawableJoystick].           */          private fun initializeOverlayJoystick(              context: Context, @@ -1117,7 +1237,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :              pressedResInner: Int,              joystick: Int,              button: Int, -            orientation: String +            prefId: String, +            layout: String          ): InputOverlayDrawableJoystick {              // Resources handle for fetching the initial Drawable resource.              val res = context.resources @@ -1141,8 +1262,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :              // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.              // These were set in the input overlay configuration menu. -            val drawableXPercent = sPrefs.getFloat("$button-X$orientation", 0f) -            val drawableYPercent = sPrefs.getFloat("$button-Y$orientation", 0f) +            val drawableXPercent = sPrefs.getFloat("$prefId-X$layout", 0f) +            val drawableYPercent = sPrefs.getFloat("$prefId-Y$layout", 0f)              val drawableX = (drawableXPercent * max.x + min.x).toInt()              val drawableY = (drawableYPercent * max.y + min.y).toInt()              val outerScale = 1.66f @@ -1168,7 +1289,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :                  outerRect,                  innerRect,                  joystick, -                button +                button, +                prefId              )              // Need to set the image's position diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt index 4a93e0b14..2c28dda88 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt @@ -24,7 +24,8 @@ class InputOverlayDrawableButton(      res: Resources,      defaultStateBitmap: Bitmap,      pressedStateBitmap: Bitmap, -    val buttonId: Int +    val buttonId: Int, +    val prefId: String  ) {      // The ID value what motion event is tracking      var trackId: Int diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt index fb48f584d..518b1e783 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt @@ -37,7 +37,8 @@ class InputOverlayDrawableJoystick(      rectOuter: Rect,      rectInner: Rect,      val joystickId: Int, -    val buttonId: Int +    val buttonId: Int, +    val prefId: String  ) {      // The ID value what motion event is tracking      var trackId = -1 diff --git a/src/android/app/src/main/res/drawable/button_l3.xml b/src/android/app/src/main/res/drawable/button_l3.xml new file mode 100644 index 000000000..0cb28836e --- /dev/null +++ b/src/android/app/src/main/res/drawable/button_l3.xml @@ -0,0 +1,128 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:aapt="http://schemas.android.com/aapt" +    android:width="34.963dp" +    android:height="37.265dp" +    android:viewportWidth="34.963" +    android:viewportHeight="37.265"> +    <path +        android:fillAlpha="0.5" +        android:pathData="M19.451,19.024A3.498,3.498 0,0 0,21.165 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L20.327,16.481L20.327,15.7L20.901,15.7c0.757,0 1.714,-0.392 1.714,-1.302C22.621,13.785 22.224,13.229 21.271,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C23.967,19.27 23.017,20.346 21.165,20.346a3.929,3.929 135,0 1,-1.998 -0.529z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="21.568" +                android:endY="33.938" +                android:startX="21.568" +                android:startY="16.14" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +    <path +        android:fillAlpha="0.5" +        android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="17.395" +                android:endY="18.74" +                android:startX="17.395" +                android:startY="-1.296" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +    <path +        android:fillAlpha="0.5" +        android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:centerX="17.477" +                android:centerY="19.92" +                android:gradientRadius="17.201" +                android:type="radial"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0.58" /> +                <item +                    android:color="#FFC6C6C6" +                    android:offset="0.84" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.88" /> +                <item +                    android:color="#FFC2C2C2" +                    android:offset="0.91" /> +                <item +                    android:color="#FFB5B5B5" +                    android:offset="0.94" /> +                <item +                    android:color="#FF9E9E9E" +                    android:offset="0.98" /> +                <item +                    android:color="#FF8F8F8F" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +    <path +        android:fillAlpha="0.5" +        android:pathData="m12.516,12.729l2,0l0,13.822l6.615,0l0,1.68L12.516,28.231Z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="16.829" +                android:endY="46.882" +                android:startX="16.829" +                android:startY="20.479" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +</vector> diff --git a/src/android/app/src/main/res/drawable/button_l3_depressed.xml b/src/android/app/src/main/res/drawable/button_l3_depressed.xml new file mode 100644 index 000000000..b078dedc9 --- /dev/null +++ b/src/android/app/src/main/res/drawable/button_l3_depressed.xml @@ -0,0 +1,75 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:aapt="http://schemas.android.com/aapt" +    android:width="34.963dp" +    android:height="37.265dp" +    android:viewportWidth="34.963" +    android:viewportHeight="37.265"> +    <path +        android:fillAlpha="0.3" +        android:fillColor="#151515" +        android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z" +        android:strokeAlpha="0.3" /> +    <path +        android:fillAlpha="0.6" +        android:fillColor="#151515" +        android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z" +        android:strokeAlpha="0.6" /> +    <path +        android:fillAlpha="0.6" +        android:pathData="M19.451,19.024A3.498,3.498 0,0 0,21.165 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L20.327,16.481L20.327,15.7L20.901,15.7c0.757,0 1.714,-0.392 1.714,-1.302C22.621,13.785 22.224,13.229 21.271,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C23.967,19.27 23.017,20.346 21.165,20.346a3.929,3.929 135,0 1,-1.998 -0.529z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="21.568" +                android:endY="33.938" +                android:startX="21.568" +                android:startY="16.14" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +    <path +        android:fillAlpha="0.6" +        android:pathData="m12.516,12.729l2,0l0,13.822l6.615,0l0,1.68L12.516,28.231Z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="16.829" +                android:endY="46.882" +                android:startX="16.829" +                android:startY="20.479" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +</vector> diff --git a/src/android/app/src/main/res/drawable/button_r3.xml b/src/android/app/src/main/res/drawable/button_r3.xml new file mode 100644 index 000000000..5c6864e26 --- /dev/null +++ b/src/android/app/src/main/res/drawable/button_r3.xml @@ -0,0 +1,128 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:aapt="http://schemas.android.com/aapt" +    android:width="34.963dp" +    android:height="37.265dp" +    android:viewportWidth="34.963" +    android:viewportHeight="37.265"> +    <path +        android:fillAlpha="0.5" +        android:pathData="m10.781,12.65a19.579,19.579 0,0 1,3.596 -0.302c2.003,0 3.294,0.368 4.199,1.185a3.622,3.622 0,0 1,1.14 2.757c0,1.916 -1.206,3.175 -2.733,3.704l0,0.063c1.119,0.386 1.786,1.421 2.117,2.929 0.474,2.024 0.818,3.424 1.119,3.982l-1.924,0c-0.238,-0.407 -0.561,-1.656 -0.968,-3.466 -0.431,-2.003 -1.206,-2.757 -2.91,-2.82l-1.762,0l0,6.286l-1.873,0zM12.654,19.264l1.916,0c2.003,0 3.273,-1.098 3.273,-2.757 0,-1.873 -1.357,-2.691 -3.336,-2.712a7.649,7.649 0,0 0,-1.852 0.172z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="15.506" +                android:endY="48.977" +                android:startX="15.506" +                android:startY="19.659" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +    <path +        android:fillAlpha="0.5" +        android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="17.395" +                android:endY="18.74" +                android:startX="17.395" +                android:startY="-1.296" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +    <path +        android:fillAlpha="0.5" +        android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:centerX="17.477" +                android:centerY="19.92" +                android:gradientRadius="17.201" +                android:type="radial"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0.58" /> +                <item +                    android:color="#FFC6C6C6" +                    android:offset="0.84" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.88" /> +                <item +                    android:color="#FFC2C2C2" +                    android:offset="0.91" /> +                <item +                    android:color="#FFB5B5B5" +                    android:offset="0.94" /> +                <item +                    android:color="#FF9E9E9E" +                    android:offset="0.98" /> +                <item +                    android:color="#FF8F8F8F" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +    <path +        android:fillAlpha="0.5" +        android:pathData="M21.832,19.024A3.498,3.498 0,0 0,23.547 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L22.708,16.481L22.708,15.7L23.282,15.7c0.757,0 1.714,-0.392 1.714,-1.302C25.002,13.785 24.605,13.229 23.652,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C26.349,19.27 25.399,20.346 23.547,20.346a3.929,3.929 135,0 1,-1.998 -0.529z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="23.949" +                android:endY="33.938" +                android:startX="23.949" +                android:startY="16.14" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +</vector> diff --git a/src/android/app/src/main/res/drawable/button_r3_depressed.xml b/src/android/app/src/main/res/drawable/button_r3_depressed.xml new file mode 100644 index 000000000..20f480179 --- /dev/null +++ b/src/android/app/src/main/res/drawable/button_r3_depressed.xml @@ -0,0 +1,75 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:aapt="http://schemas.android.com/aapt" +    android:width="34.963dp" +    android:height="37.265dp" +    android:viewportWidth="34.963" +    android:viewportHeight="37.265"> +    <path +        android:fillAlpha="0.3" +        android:fillColor="#151515" +        android:pathData="M16.062,9.353 L9.624,3.405A1.963,1.963 0,0 1,10.955 0l12.88,0a1.963,1.963 135,0 1,1.323 3.405L18.726,9.353a1.961,1.961 135,0 1,-2.664 0z" +        android:strokeAlpha="0.3" /> +    <path +        android:fillAlpha="0.6" +        android:fillColor="#151515" +        android:pathData="m25.79,5.657l0,0a2.09,2.09 45,0 0,0.23 3.262c3.522,2.402 4.762,5.927 4.741,10.52A13.279,13.279 135,0 1,4.206 19.365c0,-4.516 0.931,-7.71 4.374,-10.107a2.098,2.098 0,0 0,0.233 -3.265l0,0a2.101,2.101 135,0 0,-2.646 -0.169C1.433,9.133 -0.266,13.941 0.033,20.233a17.468,17.468 0,0 0,34.925 -0.868c0,-6.006 -1.971,-10.771 -6.585,-13.917a2.088,2.088 45,0 0,-2.582 0.209z" +        android:strokeAlpha="0.6" /> +    <path +        android:fillAlpha="0.6" +        android:pathData="m10.781,12.65a19.579,19.579 0,0 1,3.596 -0.302c2.003,0 3.294,0.368 4.199,1.185a3.622,3.622 0,0 1,1.14 2.757c0,1.916 -1.206,3.175 -2.733,3.704l0,0.063c1.119,0.386 1.786,1.421 2.117,2.929 0.474,2.024 0.818,3.424 1.119,3.982l-1.924,0c-0.238,-0.407 -0.561,-1.656 -0.968,-3.466 -0.431,-2.003 -1.206,-2.757 -2.91,-2.82l-1.762,0l0,6.286l-1.873,0zM12.654,19.264l1.916,0c2.003,0 3.273,-1.098 3.273,-2.757 0,-1.873 -1.357,-2.691 -3.336,-2.712a7.649,7.649 0,0 0,-1.852 0.172z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="15.506" +                android:endY="48.977" +                android:startX="15.506" +                android:startY="19.659" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +    <path +        android:fillAlpha="0.6" +        android:pathData="M21.832,19.024A3.498,3.498 0,0 0,23.547 19.508c1.336,0 1.749,-0.852 1.738,-1.49 0,-1.077 -0.982,-1.537 -1.987,-1.537L22.708,16.481L22.708,15.7L23.282,15.7c0.757,0 1.714,-0.392 1.714,-1.302C25.002,13.785 24.605,13.229 23.652,13.229a2.834,2.834 0,0 0,-1.537 0.529l-0.265,-0.757a3.662,3.662 0,0 1,2.008 -0.59c1.513,0 2.201,0.897 2.201,1.834 0,0.794 -0.474,1.466 -1.421,1.807l0,0.024c0.947,0.19 1.714,0.9 1.714,1.976C26.349,19.27 25.399,20.346 23.547,20.346a3.929,3.929 135,0 1,-1.998 -0.529z" +        android:strokeAlpha="0.6"> +        <aapt:attr name="android:fillColor"> +            <gradient +                android:endX="23.949" +                android:endY="33.938" +                android:startX="23.949" +                android:startY="16.14" +                android:type="linear"> +                <item +                    android:color="#FFC3C4C5" +                    android:offset="0" /> +                <item +                    android:color="#FFC5C6C6" +                    android:offset="0.03" /> +                <item +                    android:color="#FFC7C7C7" +                    android:offset="0.19" /> +                <item +                    android:color="#DBB5B5B5" +                    android:offset="0.44" /> +                <item +                    android:color="#7F878787" +                    android:offset="1" /> +            </gradient> +        </aapt:attr> +    </path> +</vector> diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 6d092f7a9..200b99185 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -205,6 +205,8 @@          <item>@string/gamepad_d_pad</item>          <item>@string/gamepad_left_stick</item>          <item>@string/gamepad_right_stick</item> +        <item>L3</item> +        <item>R3</item>          <item>@string/gamepad_home</item>          <item>@string/gamepad_screenshot</item>      </string-array> diff --git a/src/android/app/src/main/res/values/integers.xml b/src/android/app/src/main/res/values/integers.xml index 2e93b408c..5e39bc7d9 100644 --- a/src/android/app/src/main/res/values/integers.xml +++ b/src/android/app/src/main/res/values/integers.xml @@ -33,6 +33,10 @@      <integer name="SWITCH_BUTTON_CAPTURE_Y">950</integer>      <integer name="SWITCH_BUTTON_DPAD_X">260</integer>      <integer name="SWITCH_BUTTON_DPAD_Y">790</integer> +    <integer name="SWITCH_BUTTON_STICK_L_X">870</integer> +    <integer name="SWITCH_BUTTON_STICK_L_Y">400</integer> +    <integer name="SWITCH_BUTTON_STICK_R_X">960</integer> +    <integer name="SWITCH_BUTTON_STICK_R_Y">430</integer>      <!-- Default SWITCH portrait layout -->      <integer name="SWITCH_BUTTON_A_X_PORTRAIT">840</integer> @@ -65,6 +69,10 @@      <integer name="SWITCH_BUTTON_CAPTURE_Y_PORTRAIT">950</integer>      <integer name="SWITCH_BUTTON_DPAD_X_PORTRAIT">240</integer>      <integer name="SWITCH_BUTTON_DPAD_Y_PORTRAIT">840</integer> +    <integer name="SWITCH_BUTTON_STICK_L_X_PORTRAIT">730</integer> +    <integer name="SWITCH_BUTTON_STICK_L_Y_PORTRAIT">510</integer> +    <integer name="SWITCH_BUTTON_STICK_R_X_PORTRAIT">900</integer> +    <integer name="SWITCH_BUTTON_STICK_R_Y_PORTRAIT">540</integer>      <!-- Default SWITCH foldable layout -->      <integer name="SWITCH_BUTTON_A_X_FOLDABLE">840</integer> @@ -97,5 +105,9 @@      <integer name="SWITCH_BUTTON_CAPTURE_Y_FOLDABLE">470</integer>      <integer name="SWITCH_BUTTON_DPAD_X_FOLDABLE">240</integer>      <integer name="SWITCH_BUTTON_DPAD_Y_FOLDABLE">390</integer> +    <integer name="SWITCH_BUTTON_STICK_L_X_FOLDABLE">550</integer> +    <integer name="SWITCH_BUTTON_STICK_L_Y_FOLDABLE">210</integer> +    <integer name="SWITCH_BUTTON_STICK_R_X_FOLDABLE">550</integer> +    <integer name="SWITCH_BUTTON_STICK_R_Y_FOLDABLE">280</integer>  </resources> | 
