diff options
| author | 2023-06-01 17:49:20 +0200 | |
|---|---|---|
| committer | 2023-06-03 00:06:07 -0700 | |
| commit | a7e0a0d5b10e1a2cd1ba46d7b3014d7b9997fea0 (patch) | |
| tree | 993acc27cd976cf4c011d81d6eb1b71d7c640d2f /src/android | |
| parent | android: Don't crash the app when selecting a zip that causes a SecurityExcep... (diff) | |
| download | yuzu-a7e0a0d5b10e1a2cd1ba46d7b3014d7b9997fea0.tar.gz yuzu-a7e0a0d5b10e1a2cd1ba46d7b3014d7b9997fea0.tar.xz yuzu-a7e0a0d5b10e1a2cd1ba46d7b3014d7b9997fea0.zip | |
Save the position of buttons as a percentage
Diffstat (limited to 'src/android')
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt | 216 |
1 files changed, 136 insertions, 80 deletions
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 f0b0af9e5..bb20e5207 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 | |||
| @@ -9,6 +9,7 @@ import android.content.SharedPreferences | |||
| 9 | import android.content.res.Configuration | 9 | import android.content.res.Configuration |
| 10 | import android.graphics.Bitmap | 10 | import android.graphics.Bitmap |
| 11 | import android.graphics.Canvas | 11 | import android.graphics.Canvas |
| 12 | import android.graphics.Point | ||
| 12 | import android.graphics.Rect | 13 | import android.graphics.Rect |
| 13 | import android.graphics.drawable.Drawable | 14 | import android.graphics.drawable.Drawable |
| 14 | import android.graphics.drawable.VectorDrawable | 15 | import android.graphics.drawable.VectorDrawable |
| @@ -343,10 +344,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 343 | } | 344 | } |
| 344 | 345 | ||
| 345 | private fun addOverlayControls(orientation: String) { | 346 | private fun addOverlayControls(orientation: String) { |
| 347 | val windowSize = getSafeScreenSize(context) | ||
| 346 | if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_0, true)) { | 348 | if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_0, true)) { |
| 347 | overlayButtons.add( | 349 | overlayButtons.add( |
| 348 | initializeOverlayButton( | 350 | initializeOverlayButton( |
| 349 | context, | 351 | context, |
| 352 | windowSize, | ||
| 350 | R.drawable.facebutton_a, | 353 | R.drawable.facebutton_a, |
| 351 | R.drawable.facebutton_a_depressed, | 354 | R.drawable.facebutton_a_depressed, |
| 352 | ButtonType.BUTTON_A, | 355 | ButtonType.BUTTON_A, |
| @@ -358,6 +361,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 358 | overlayButtons.add( | 361 | overlayButtons.add( |
| 359 | initializeOverlayButton( | 362 | initializeOverlayButton( |
| 360 | context, | 363 | context, |
| 364 | windowSize, | ||
| 361 | R.drawable.facebutton_b, | 365 | R.drawable.facebutton_b, |
| 362 | R.drawable.facebutton_b_depressed, | 366 | R.drawable.facebutton_b_depressed, |
| 363 | ButtonType.BUTTON_B, | 367 | ButtonType.BUTTON_B, |
| @@ -369,6 +373,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 369 | overlayButtons.add( | 373 | overlayButtons.add( |
| 370 | initializeOverlayButton( | 374 | initializeOverlayButton( |
| 371 | context, | 375 | context, |
| 376 | windowSize, | ||
| 372 | R.drawable.facebutton_x, | 377 | R.drawable.facebutton_x, |
| 373 | R.drawable.facebutton_x_depressed, | 378 | R.drawable.facebutton_x_depressed, |
| 374 | ButtonType.BUTTON_X, | 379 | ButtonType.BUTTON_X, |
| @@ -380,6 +385,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 380 | overlayButtons.add( | 385 | overlayButtons.add( |
| 381 | initializeOverlayButton( | 386 | initializeOverlayButton( |
| 382 | context, | 387 | context, |
| 388 | windowSize, | ||
| 383 | R.drawable.facebutton_y, | 389 | R.drawable.facebutton_y, |
| 384 | R.drawable.facebutton_y_depressed, | 390 | R.drawable.facebutton_y_depressed, |
| 385 | ButtonType.BUTTON_Y, | 391 | ButtonType.BUTTON_Y, |
| @@ -391,6 +397,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 391 | overlayButtons.add( | 397 | overlayButtons.add( |
| 392 | initializeOverlayButton( | 398 | initializeOverlayButton( |
| 393 | context, | 399 | context, |
| 400 | windowSize, | ||
| 394 | R.drawable.l_shoulder, | 401 | R.drawable.l_shoulder, |
| 395 | R.drawable.l_shoulder_depressed, | 402 | R.drawable.l_shoulder_depressed, |
| 396 | ButtonType.TRIGGER_L, | 403 | ButtonType.TRIGGER_L, |
| @@ -402,6 +409,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 402 | overlayButtons.add( | 409 | overlayButtons.add( |
| 403 | initializeOverlayButton( | 410 | initializeOverlayButton( |
| 404 | context, | 411 | context, |
| 412 | windowSize, | ||
| 405 | R.drawable.r_shoulder, | 413 | R.drawable.r_shoulder, |
| 406 | R.drawable.r_shoulder_depressed, | 414 | R.drawable.r_shoulder_depressed, |
| 407 | ButtonType.TRIGGER_R, | 415 | ButtonType.TRIGGER_R, |
| @@ -413,6 +421,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 413 | overlayButtons.add( | 421 | overlayButtons.add( |
| 414 | initializeOverlayButton( | 422 | initializeOverlayButton( |
| 415 | context, | 423 | context, |
| 424 | windowSize, | ||
| 416 | R.drawable.zl_trigger, | 425 | R.drawable.zl_trigger, |
| 417 | R.drawable.zl_trigger_depressed, | 426 | R.drawable.zl_trigger_depressed, |
| 418 | ButtonType.TRIGGER_ZL, | 427 | ButtonType.TRIGGER_ZL, |
| @@ -424,6 +433,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 424 | overlayButtons.add( | 433 | overlayButtons.add( |
| 425 | initializeOverlayButton( | 434 | initializeOverlayButton( |
| 426 | context, | 435 | context, |
| 436 | windowSize, | ||
| 427 | R.drawable.zr_trigger, | 437 | R.drawable.zr_trigger, |
| 428 | R.drawable.zr_trigger_depressed, | 438 | R.drawable.zr_trigger_depressed, |
| 429 | ButtonType.TRIGGER_ZR, | 439 | ButtonType.TRIGGER_ZR, |
| @@ -435,6 +445,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 435 | overlayButtons.add( | 445 | overlayButtons.add( |
| 436 | initializeOverlayButton( | 446 | initializeOverlayButton( |
| 437 | context, | 447 | context, |
| 448 | windowSize, | ||
| 438 | R.drawable.facebutton_plus, | 449 | R.drawable.facebutton_plus, |
| 439 | R.drawable.facebutton_plus_depressed, | 450 | R.drawable.facebutton_plus_depressed, |
| 440 | ButtonType.BUTTON_PLUS, | 451 | ButtonType.BUTTON_PLUS, |
| @@ -446,6 +457,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 446 | overlayButtons.add( | 457 | overlayButtons.add( |
| 447 | initializeOverlayButton( | 458 | initializeOverlayButton( |
| 448 | context, | 459 | context, |
| 460 | windowSize, | ||
| 449 | R.drawable.facebutton_minus, | 461 | R.drawable.facebutton_minus, |
| 450 | R.drawable.facebutton_minus_depressed, | 462 | R.drawable.facebutton_minus_depressed, |
| 451 | ButtonType.BUTTON_MINUS, | 463 | ButtonType.BUTTON_MINUS, |
| @@ -457,6 +469,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 457 | overlayDpads.add( | 469 | overlayDpads.add( |
| 458 | initializeOverlayDpad( | 470 | initializeOverlayDpad( |
| 459 | context, | 471 | context, |
| 472 | windowSize, | ||
| 460 | R.drawable.dpad_standard, | 473 | R.drawable.dpad_standard, |
| 461 | R.drawable.dpad_standard_cardinal_depressed, | 474 | R.drawable.dpad_standard_cardinal_depressed, |
| 462 | R.drawable.dpad_standard_diagonal_depressed, | 475 | R.drawable.dpad_standard_diagonal_depressed, |
| @@ -468,6 +481,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 468 | overlayJoysticks.add( | 481 | overlayJoysticks.add( |
| 469 | initializeOverlayJoystick( | 482 | initializeOverlayJoystick( |
| 470 | context, | 483 | context, |
| 484 | windowSize, | ||
| 471 | R.drawable.joystick_range, | 485 | R.drawable.joystick_range, |
| 472 | R.drawable.joystick, | 486 | R.drawable.joystick, |
| 473 | R.drawable.joystick_depressed, | 487 | R.drawable.joystick_depressed, |
| @@ -481,6 +495,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 481 | overlayJoysticks.add( | 495 | overlayJoysticks.add( |
| 482 | initializeOverlayJoystick( | 496 | initializeOverlayJoystick( |
| 483 | context, | 497 | context, |
| 498 | windowSize, | ||
| 484 | R.drawable.joystick_range, | 499 | R.drawable.joystick_range, |
| 485 | R.drawable.joystick, | 500 | R.drawable.joystick, |
| 486 | R.drawable.joystick_depressed, | 501 | R.drawable.joystick_depressed, |
| @@ -494,6 +509,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 494 | overlayButtons.add( | 509 | overlayButtons.add( |
| 495 | initializeOverlayButton( | 510 | initializeOverlayButton( |
| 496 | context, | 511 | context, |
| 512 | windowSize, | ||
| 497 | R.drawable.facebutton_home, | 513 | R.drawable.facebutton_home, |
| 498 | R.drawable.facebutton_home_depressed, | 514 | R.drawable.facebutton_home_depressed, |
| 499 | ButtonType.BUTTON_HOME, | 515 | ButtonType.BUTTON_HOME, |
| @@ -505,6 +521,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 505 | overlayButtons.add( | 521 | overlayButtons.add( |
| 506 | initializeOverlayButton( | 522 | initializeOverlayButton( |
| 507 | context, | 523 | context, |
| 524 | windowSize, | ||
| 508 | R.drawable.facebutton_screenshot, | 525 | R.drawable.facebutton_screenshot, |
| 509 | R.drawable.facebutton_screenshot_depressed, | 526 | R.drawable.facebutton_screenshot_depressed, |
| 510 | ButtonType.BUTTON_CAPTURE, | 527 | ButtonType.BUTTON_CAPTURE, |
| @@ -530,9 +547,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 530 | } | 547 | } |
| 531 | 548 | ||
| 532 | private fun saveControlPosition(sharedPrefsId: Int, x: Int, y: Int, orientation: String) { | 549 | private fun saveControlPosition(sharedPrefsId: Int, x: Int, y: Int, orientation: String) { |
| 550 | val windowSize = getSafeScreenSize(context) | ||
| 551 | val min = windowSize.first | ||
| 552 | val max = windowSize.second | ||
| 533 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit() | 553 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit() |
| 534 | .putFloat("$sharedPrefsId$orientation-X", x.toFloat()) | 554 | .putFloat("$sharedPrefsId$orientation-X", (x - min.x).toFloat() / max.x) |
| 535 | .putFloat("$sharedPrefsId$orientation-Y", y.toFloat()) | 555 | .putFloat("$sharedPrefsId$orientation-Y", (y - min.y).toFloat() / max.y) |
| 536 | .apply() | 556 | .apply() |
| 537 | } | 557 | } |
| 538 | 558 | ||
| @@ -557,170 +577,129 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 557 | } | 577 | } |
| 558 | 578 | ||
| 559 | private fun defaultOverlayLandscape() { | 579 | private fun defaultOverlayLandscape() { |
| 560 | // Get screen size | 580 | // Each value represents the position of the button in relation to the screen size without insets. |
| 561 | val windowMetrics = | ||
| 562 | WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context as Activity) | ||
| 563 | var maxY = windowMetrics.bounds.height().toFloat() | ||
| 564 | var maxX = windowMetrics.bounds.width().toFloat() | ||
| 565 | var minY = 0 | ||
| 566 | var minX = 0 | ||
| 567 | |||
| 568 | // If we have API access, calculate the safe area to draw the overlay | ||
| 569 | var cutoutLeft = 0 | ||
| 570 | var cutoutBottom = 0 | ||
| 571 | val insets = windowInsets.displayCutout | ||
| 572 | if (insets != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { | ||
| 573 | maxY = | ||
| 574 | if (insets.boundingRectTop.bottom != 0) insets.boundingRectTop.bottom.toFloat() else maxY | ||
| 575 | maxX = | ||
| 576 | if (insets.boundingRectRight.left != 0) insets.boundingRectRight.left.toFloat() else maxX | ||
| 577 | minX = insets.boundingRectLeft.right - insets.boundingRectLeft.left | ||
| 578 | minY = insets.boundingRectBottom.top - insets.boundingRectBottom.bottom | ||
| 579 | |||
| 580 | cutoutLeft = insets.boundingRectRight.right - insets.boundingRectRight.left | ||
| 581 | cutoutBottom = insets.boundingRectTop.top - insets.boundingRectTop.bottom | ||
| 582 | } | ||
| 583 | |||
| 584 | // This makes sure that if we have an inset on one side of the screen, we mirror it on | ||
| 585 | // the other side. Since removing space from one of the max values messes with the scale, | ||
| 586 | // we also have to account for it using our min values. | ||
| 587 | if (maxX.toInt() != windowMetrics.bounds.width()) minX += cutoutLeft | ||
| 588 | if (maxY.toInt() != windowMetrics.bounds.height()) minY += cutoutBottom | ||
| 589 | if (minX > 0 && maxX.toInt() == windowMetrics.bounds.width()) { | ||
| 590 | maxX -= (minX * 2) | ||
| 591 | } else if (minX > 0) { | ||
| 592 | maxX -= minX | ||
| 593 | } | ||
| 594 | if (minY > 0 && maxY.toInt() == windowMetrics.bounds.height()) { | ||
| 595 | maxY -= (minY * 2) | ||
| 596 | } else if (minY > 0) { | ||
| 597 | maxY -= minY | ||
| 598 | } | ||
| 599 | |||
| 600 | // Each value is a percent from max X/Y stored as an int. Have to bring that value down | ||
| 601 | // to a decimal before multiplying by MAX X/Y. | ||
| 602 | preferences.edit() | 581 | preferences.edit() |
| 603 | .putFloat( | 582 | .putFloat( |
| 604 | ButtonType.BUTTON_A.toString() + "-X", | 583 | ButtonType.BUTTON_A.toString() + "-X", |
| 605 | resources.getInteger(R.integer.SWITCH_BUTTON_A_X).toFloat() / 1000 * maxX + minX | 584 | resources.getInteger(R.integer.SWITCH_BUTTON_A_X).toFloat() / 1000 |
| 606 | ) | 585 | ) |
| 607 | .putFloat( | 586 | .putFloat( |
| 608 | ButtonType.BUTTON_A.toString() + "-Y", | 587 | ButtonType.BUTTON_A.toString() + "-Y", |
| 609 | resources.getInteger(R.integer.SWITCH_BUTTON_A_Y).toFloat() / 1000 * maxY + minY | 588 | resources.getInteger(R.integer.SWITCH_BUTTON_A_Y).toFloat() / 1000 |
| 610 | ) | 589 | ) |
| 611 | .putFloat( | 590 | .putFloat( |
| 612 | ButtonType.BUTTON_B.toString() + "-X", | 591 | ButtonType.BUTTON_B.toString() + "-X", |
| 613 | resources.getInteger(R.integer.SWITCH_BUTTON_B_X).toFloat() / 1000 * maxX + minX | 592 | resources.getInteger(R.integer.SWITCH_BUTTON_B_X).toFloat() / 1000 |
| 614 | ) | 593 | ) |
| 615 | .putFloat( | 594 | .putFloat( |
| 616 | ButtonType.BUTTON_B.toString() + "-Y", | 595 | ButtonType.BUTTON_B.toString() + "-Y", |
| 617 | resources.getInteger(R.integer.SWITCH_BUTTON_B_Y).toFloat() / 1000 * maxY + minY | 596 | resources.getInteger(R.integer.SWITCH_BUTTON_B_Y).toFloat() / 1000 |
| 618 | ) | 597 | ) |
| 619 | .putFloat( | 598 | .putFloat( |
| 620 | ButtonType.BUTTON_X.toString() + "-X", | 599 | ButtonType.BUTTON_X.toString() + "-X", |
| 621 | resources.getInteger(R.integer.SWITCH_BUTTON_X_X).toFloat() / 1000 * maxX + minX | 600 | resources.getInteger(R.integer.SWITCH_BUTTON_X_X).toFloat() / 1000 |
| 622 | ) | 601 | ) |
| 623 | .putFloat( | 602 | .putFloat( |
| 624 | ButtonType.BUTTON_X.toString() + "-Y", | 603 | ButtonType.BUTTON_X.toString() + "-Y", |
| 625 | resources.getInteger(R.integer.SWITCH_BUTTON_X_Y).toFloat() / 1000 * maxY + minY | 604 | resources.getInteger(R.integer.SWITCH_BUTTON_X_Y).toFloat() / 1000 |
| 626 | ) | 605 | ) |
| 627 | .putFloat( | 606 | .putFloat( |
| 628 | ButtonType.BUTTON_Y.toString() + "-X", | 607 | ButtonType.BUTTON_Y.toString() + "-X", |
| 629 | resources.getInteger(R.integer.SWITCH_BUTTON_Y_X).toFloat() / 1000 * maxX + minX | 608 | resources.getInteger(R.integer.SWITCH_BUTTON_Y_X).toFloat() / 1000 |
| 630 | ) | 609 | ) |
| 631 | .putFloat( | 610 | .putFloat( |
| 632 | ButtonType.BUTTON_Y.toString() + "-Y", | 611 | ButtonType.BUTTON_Y.toString() + "-Y", |
| 633 | resources.getInteger(R.integer.SWITCH_BUTTON_Y_Y).toFloat() / 1000 * maxY + minY | 612 | resources.getInteger(R.integer.SWITCH_BUTTON_Y_Y).toFloat() / 1000 |
| 634 | ) | 613 | ) |
| 635 | .putFloat( | 614 | .putFloat( |
| 636 | ButtonType.TRIGGER_ZL.toString() + "-X", | 615 | ButtonType.TRIGGER_ZL.toString() + "-X", |
| 637 | resources.getInteger(R.integer.SWITCH_TRIGGER_ZL_X).toFloat() / 1000 * maxX + minX | 616 | resources.getInteger(R.integer.SWITCH_TRIGGER_ZL_X).toFloat() / 1000 |
| 638 | ) | 617 | ) |
| 639 | .putFloat( | 618 | .putFloat( |
| 640 | ButtonType.TRIGGER_ZL.toString() + "-Y", | 619 | ButtonType.TRIGGER_ZL.toString() + "-Y", |
| 641 | resources.getInteger(R.integer.SWITCH_TRIGGER_ZL_Y).toFloat() / 1000 * maxY + minY | 620 | resources.getInteger(R.integer.SWITCH_TRIGGER_ZL_Y).toFloat() / 1000 |
| 642 | ) | 621 | ) |
| 643 | .putFloat( | 622 | .putFloat( |
| 644 | ButtonType.TRIGGER_ZR.toString() + "-X", | 623 | ButtonType.TRIGGER_ZR.toString() + "-X", |
| 645 | resources.getInteger(R.integer.SWITCH_TRIGGER_ZR_X).toFloat() / 1000 * maxX + minX | 624 | resources.getInteger(R.integer.SWITCH_TRIGGER_ZR_X).toFloat() / 1000 |
| 646 | ) | 625 | ) |
| 647 | .putFloat( | 626 | .putFloat( |
| 648 | ButtonType.TRIGGER_ZR.toString() + "-Y", | 627 | ButtonType.TRIGGER_ZR.toString() + "-Y", |
| 649 | resources.getInteger(R.integer.SWITCH_TRIGGER_ZR_Y).toFloat() / 1000 * maxY + minY | 628 | resources.getInteger(R.integer.SWITCH_TRIGGER_ZR_Y).toFloat() / 1000 |
| 650 | ) | 629 | ) |
| 651 | .putFloat( | 630 | .putFloat( |
| 652 | ButtonType.DPAD_UP.toString() + "-X", | 631 | ButtonType.DPAD_UP.toString() + "-X", |
| 653 | resources.getInteger(R.integer.SWITCH_BUTTON_DPAD_X).toFloat() / 1000 * maxX + minX | 632 | resources.getInteger(R.integer.SWITCH_BUTTON_DPAD_X).toFloat() / 1000 |
| 654 | ) | 633 | ) |
| 655 | .putFloat( | 634 | .putFloat( |
| 656 | ButtonType.DPAD_UP.toString() + "-Y", | 635 | ButtonType.DPAD_UP.toString() + "-Y", |
| 657 | resources.getInteger(R.integer.SWITCH_BUTTON_DPAD_Y).toFloat() / 1000 * maxY + minY | 636 | resources.getInteger(R.integer.SWITCH_BUTTON_DPAD_Y).toFloat() / 1000 |
| 658 | ) | 637 | ) |
| 659 | .putFloat( | 638 | .putFloat( |
| 660 | ButtonType.TRIGGER_L.toString() + "-X", | 639 | ButtonType.TRIGGER_L.toString() + "-X", |
| 661 | resources.getInteger(R.integer.SWITCH_TRIGGER_L_X).toFloat() / 1000 * maxX + minX | 640 | resources.getInteger(R.integer.SWITCH_TRIGGER_L_X).toFloat() / 1000 |
| 662 | ) | 641 | ) |
| 663 | .putFloat( | 642 | .putFloat( |
| 664 | ButtonType.TRIGGER_L.toString() + "-Y", | 643 | ButtonType.TRIGGER_L.toString() + "-Y", |
| 665 | resources.getInteger(R.integer.SWITCH_TRIGGER_L_Y).toFloat() / 1000 * maxY + minY | 644 | resources.getInteger(R.integer.SWITCH_TRIGGER_L_Y).toFloat() / 1000 |
| 666 | ) | 645 | ) |
| 667 | .putFloat( | 646 | .putFloat( |
| 668 | ButtonType.TRIGGER_R.toString() + "-X", | 647 | ButtonType.TRIGGER_R.toString() + "-X", |
| 669 | resources.getInteger(R.integer.SWITCH_TRIGGER_R_X).toFloat() / 1000 * maxX + minX | 648 | resources.getInteger(R.integer.SWITCH_TRIGGER_R_X).toFloat() / 1000 |
| 670 | ) | 649 | ) |
| 671 | .putFloat( | 650 | .putFloat( |
| 672 | ButtonType.TRIGGER_R.toString() + "-Y", | 651 | ButtonType.TRIGGER_R.toString() + "-Y", |
| 673 | resources.getInteger(R.integer.SWITCH_TRIGGER_R_Y).toFloat() / 1000 * maxY + minY | 652 | resources.getInteger(R.integer.SWITCH_TRIGGER_R_Y).toFloat() / 1000 |
| 674 | ) | 653 | ) |
| 675 | .putFloat( | 654 | .putFloat( |
| 676 | ButtonType.BUTTON_PLUS.toString() + "-X", | 655 | ButtonType.BUTTON_PLUS.toString() + "-X", |
| 677 | resources.getInteger(R.integer.SWITCH_BUTTON_PLUS_X).toFloat() / 1000 * maxX + minX | 656 | resources.getInteger(R.integer.SWITCH_BUTTON_PLUS_X).toFloat() / 1000 |
| 678 | ) | 657 | ) |
| 679 | .putFloat( | 658 | .putFloat( |
| 680 | ButtonType.BUTTON_PLUS.toString() + "-Y", | 659 | ButtonType.BUTTON_PLUS.toString() + "-Y", |
| 681 | resources.getInteger(R.integer.SWITCH_BUTTON_PLUS_Y).toFloat() / 1000 * maxY + minY | 660 | resources.getInteger(R.integer.SWITCH_BUTTON_PLUS_Y).toFloat() / 1000 |
| 682 | ) | 661 | ) |
| 683 | .putFloat( | 662 | .putFloat( |
| 684 | ButtonType.BUTTON_MINUS.toString() + "-X", | 663 | ButtonType.BUTTON_MINUS.toString() + "-X", |
| 685 | resources.getInteger(R.integer.SWITCH_BUTTON_MINUS_X).toFloat() / 1000 * maxX + minX | 664 | resources.getInteger(R.integer.SWITCH_BUTTON_MINUS_X).toFloat() / 1000 |
| 686 | ) | 665 | ) |
| 687 | .putFloat( | 666 | .putFloat( |
| 688 | ButtonType.BUTTON_MINUS.toString() + "-Y", | 667 | ButtonType.BUTTON_MINUS.toString() + "-Y", |
| 689 | resources.getInteger(R.integer.SWITCH_BUTTON_MINUS_Y).toFloat() / 1000 * maxY + minY | 668 | resources.getInteger(R.integer.SWITCH_BUTTON_MINUS_Y).toFloat() / 1000 |
| 690 | ) | 669 | ) |
| 691 | .putFloat( | 670 | .putFloat( |
| 692 | ButtonType.BUTTON_HOME.toString() + "-X", | 671 | ButtonType.BUTTON_HOME.toString() + "-X", |
| 693 | resources.getInteger(R.integer.SWITCH_BUTTON_HOME_X).toFloat() / 1000 * maxX + minX | 672 | resources.getInteger(R.integer.SWITCH_BUTTON_HOME_X).toFloat() / 1000 |
| 694 | ) | 673 | ) |
| 695 | .putFloat( | 674 | .putFloat( |
| 696 | ButtonType.BUTTON_HOME.toString() + "-Y", | 675 | ButtonType.BUTTON_HOME.toString() + "-Y", |
| 697 | resources.getInteger(R.integer.SWITCH_BUTTON_HOME_Y).toFloat() / 1000 * maxY + minY | 676 | resources.getInteger(R.integer.SWITCH_BUTTON_HOME_Y).toFloat() / 1000 |
| 698 | ) | 677 | ) |
| 699 | .putFloat( | 678 | .putFloat( |
| 700 | ButtonType.BUTTON_CAPTURE.toString() + "-X", | 679 | ButtonType.BUTTON_CAPTURE.toString() + "-X", |
| 701 | resources.getInteger(R.integer.SWITCH_BUTTON_CAPTURE_X) | 680 | resources.getInteger(R.integer.SWITCH_BUTTON_CAPTURE_X) |
| 702 | .toFloat() / 1000 * maxX + minX | 681 | .toFloat() / 1000 |
| 703 | ) | 682 | ) |
| 704 | .putFloat( | 683 | .putFloat( |
| 705 | ButtonType.BUTTON_CAPTURE.toString() + "-Y", | 684 | ButtonType.BUTTON_CAPTURE.toString() + "-Y", |
| 706 | resources.getInteger(R.integer.SWITCH_BUTTON_CAPTURE_Y) | 685 | resources.getInteger(R.integer.SWITCH_BUTTON_CAPTURE_Y) |
| 707 | .toFloat() / 1000 * maxY + minY | 686 | .toFloat() / 1000 |
| 708 | ) | 687 | ) |
| 709 | .putFloat( | 688 | .putFloat( |
| 710 | ButtonType.STICK_R.toString() + "-X", | 689 | ButtonType.STICK_R.toString() + "-X", |
| 711 | resources.getInteger(R.integer.SWITCH_STICK_R_X).toFloat() / 1000 * maxX + minX | 690 | resources.getInteger(R.integer.SWITCH_STICK_R_X).toFloat() / 1000 |
| 712 | ) | 691 | ) |
| 713 | .putFloat( | 692 | .putFloat( |
| 714 | ButtonType.STICK_R.toString() + "-Y", | 693 | ButtonType.STICK_R.toString() + "-Y", |
| 715 | resources.getInteger(R.integer.SWITCH_STICK_R_Y).toFloat() / 1000 * maxY + minY | 694 | resources.getInteger(R.integer.SWITCH_STICK_R_Y).toFloat() / 1000 |
| 716 | ) | 695 | ) |
| 717 | .putFloat( | 696 | .putFloat( |
| 718 | ButtonType.STICK_L.toString() + "-X", | 697 | ButtonType.STICK_L.toString() + "-X", |
| 719 | resources.getInteger(R.integer.SWITCH_STICK_L_X).toFloat() / 1000 * maxX + minX | 698 | resources.getInteger(R.integer.SWITCH_STICK_L_X).toFloat() / 1000 |
| 720 | ) | 699 | ) |
| 721 | .putFloat( | 700 | .putFloat( |
| 722 | ButtonType.STICK_L.toString() + "-Y", | 701 | ButtonType.STICK_L.toString() + "-Y", |
| 723 | resources.getInteger(R.integer.SWITCH_STICK_L_Y).toFloat() / 1000 * maxY + minY | 702 | resources.getInteger(R.integer.SWITCH_STICK_L_Y).toFloat() / 1000 |
| 724 | ) | 703 | ) |
| 725 | .apply() | 704 | .apply() |
| 726 | } | 705 | } |
| @@ -767,6 +746,59 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 767 | } | 746 | } |
| 768 | 747 | ||
| 769 | /** | 748 | /** |
| 749 | * Gets the safe screen size for drawing the overlay | ||
| 750 | * | ||
| 751 | * @param context Context for getting the window metrics | ||
| 752 | * @return A pair of points, the first being the top left corner of the safe area, | ||
| 753 | * the second being the bottom right corner of the safe area | ||
| 754 | */ | ||
| 755 | private fun getSafeScreenSize(context: Context): Pair<Point, Point> { | ||
| 756 | // Get screen size | ||
| 757 | val windowMetrics = | ||
| 758 | WindowMetricsCalculator.getOrCreate() | ||
| 759 | .computeCurrentWindowMetrics(context as Activity) | ||
| 760 | var maxY = windowMetrics.bounds.height().toFloat() | ||
| 761 | var maxX = windowMetrics.bounds.width().toFloat() | ||
| 762 | var minY = 0 | ||
| 763 | var minX = 0 | ||
| 764 | |||
| 765 | // If we have API access, calculate the safe area to draw the overlay | ||
| 766 | var cutoutLeft = 0 | ||
| 767 | var cutoutBottom = 0 | ||
| 768 | val insets = context.windowManager.currentWindowMetrics.windowInsets.displayCutout | ||
| 769 | if (insets != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { | ||
| 770 | maxY = | ||
| 771 | if (insets.boundingRectTop.bottom != 0) insets.boundingRectTop.bottom.toFloat() else maxY | ||
| 772 | maxX = | ||
| 773 | if (insets.boundingRectRight.left != 0) insets.boundingRectRight.left.toFloat() else maxX | ||
| 774 | minX = insets.boundingRectLeft.right - insets.boundingRectLeft.left | ||
| 775 | minY = insets.boundingRectBottom.top - insets.boundingRectBottom.bottom | ||
| 776 | |||
| 777 | cutoutLeft = insets.boundingRectRight.right - insets.boundingRectRight.left | ||
| 778 | cutoutBottom = insets.boundingRectTop.top - insets.boundingRectTop.bottom | ||
| 779 | } | ||
| 780 | |||
| 781 | |||
| 782 | // This makes sure that if we have an inset on one side of the screen, we mirror it on | ||
| 783 | // the other side. Since removing space from one of the max values messes with the scale, | ||
| 784 | // we also have to account for it using our min values. | ||
| 785 | if (maxX.toInt() != windowMetrics.bounds.width()) minX += cutoutLeft | ||
| 786 | if (maxY.toInt() != windowMetrics.bounds.height()) minY += cutoutBottom | ||
| 787 | if (minX > 0 && maxX.toInt() == windowMetrics.bounds.width()) { | ||
| 788 | maxX -= (minX * 2) | ||
| 789 | } else if (minX > 0) { | ||
| 790 | maxX -= minX | ||
| 791 | } | ||
| 792 | if (minY > 0 && maxY.toInt() == windowMetrics.bounds.height()) { | ||
| 793 | maxY -= (minY * 2) | ||
| 794 | } else if (minY > 0) { | ||
| 795 | maxY -= minY | ||
| 796 | } | ||
| 797 | |||
| 798 | return Pair(Point(minX, minY), Point(maxX.toInt(), maxY.toInt())) | ||
| 799 | } | ||
| 800 | |||
| 801 | /** | ||
| 770 | * Initializes an InputOverlayDrawableButton, given by resId, with all of the | 802 | * Initializes an InputOverlayDrawableButton, given by resId, with all of the |
| 771 | * parameters set for it to be properly shown on the InputOverlay. | 803 | * parameters set for it to be properly shown on the InputOverlay. |
| 772 | * | 804 | * |
| @@ -795,6 +827,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 795 | * for Android to call the onDraw method. | 827 | * for Android to call the onDraw method. |
| 796 | * | 828 | * |
| 797 | * @param context The current [Context]. | 829 | * @param context The current [Context]. |
| 830 | * @param windowSize The size of the window to draw the overlay on. | ||
| 798 | * @param defaultResId The resource ID of the [Drawable] to get the [Bitmap] of (Default State). | 831 | * @param defaultResId The resource ID of the [Drawable] to get the [Bitmap] of (Default State). |
| 799 | * @param pressedResId The resource ID of the [Drawable] to get the [Bitmap] of (Pressed State). | 832 | * @param pressedResId The resource ID of the [Drawable] to get the [Bitmap] of (Pressed State). |
| 800 | * @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents. | 833 | * @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents. |
| @@ -802,6 +835,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 802 | */ | 835 | */ |
| 803 | private fun initializeOverlayButton( | 836 | private fun initializeOverlayButton( |
| 804 | context: Context, | 837 | context: Context, |
| 838 | windowSize: Pair<Point, Point>, | ||
| 805 | defaultResId: Int, | 839 | defaultResId: Int, |
| 806 | pressedResId: Int, | 840 | pressedResId: Int, |
| 807 | buttonId: Int, | 841 | buttonId: Int, |
| @@ -836,12 +870,18 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 836 | val overlayDrawable = | 870 | val overlayDrawable = |
| 837 | InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, buttonId) | 871 | InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, buttonId) |
| 838 | 872 | ||
| 873 | // Get the minimum and maximum coordinates of the screen where the button can be placed. | ||
| 874 | val min = windowSize.first | ||
| 875 | val max = windowSize.second | ||
| 876 | |||
| 839 | // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. | 877 | // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. |
| 840 | // These were set in the input overlay configuration menu. | 878 | // These were set in the input overlay configuration menu. |
| 841 | val xKey = "$buttonId$orientation-X" | 879 | val xKey = "$buttonId$orientation-X" |
| 842 | val yKey = "$buttonId$orientation-Y" | 880 | val yKey = "$buttonId$orientation-Y" |
| 843 | val drawableX = sPrefs.getFloat(xKey, 0f).toInt() | 881 | val drawableXPercent = sPrefs.getFloat(xKey, 0f) |
| 844 | val drawableY = sPrefs.getFloat(yKey, 0f).toInt() | 882 | val drawableYPercent = sPrefs.getFloat(yKey, 0f) |
| 883 | val drawableX = (drawableXPercent * max.x + min.x).toInt() | ||
| 884 | val drawableY = (drawableYPercent * max.y + min.y).toInt() | ||
| 845 | val width = overlayDrawable.width | 885 | val width = overlayDrawable.width |
| 846 | val height = overlayDrawable.height | 886 | val height = overlayDrawable.height |
| 847 | 887 | ||
| @@ -866,6 +906,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 866 | * Initializes an [InputOverlayDrawableDpad] | 906 | * Initializes an [InputOverlayDrawableDpad] |
| 867 | * | 907 | * |
| 868 | * @param context The current [Context]. | 908 | * @param context The current [Context]. |
| 909 | * @param windowSize The size of the window to draw the overlay on. | ||
| 869 | * @param defaultResId The [Bitmap] resource ID of the default state. | 910 | * @param defaultResId The [Bitmap] resource ID of the default state. |
| 870 | * @param pressedOneDirectionResId The [Bitmap] resource ID of the pressed state in one direction. | 911 | * @param pressedOneDirectionResId The [Bitmap] resource ID of the pressed state in one direction. |
| 871 | * @param pressedTwoDirectionsResId The [Bitmap] resource ID of the pressed state in two directions. | 912 | * @param pressedTwoDirectionsResId The [Bitmap] resource ID of the pressed state in two directions. |
| @@ -873,6 +914,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 873 | */ | 914 | */ |
| 874 | private fun initializeOverlayDpad( | 915 | private fun initializeOverlayDpad( |
| 875 | context: Context, | 916 | context: Context, |
| 917 | windowSize: Pair<Point, Point>, | ||
| 876 | defaultResId: Int, | 918 | defaultResId: Int, |
| 877 | pressedOneDirectionResId: Int, | 919 | pressedOneDirectionResId: Int, |
| 878 | pressedTwoDirectionsResId: Int, | 920 | pressedTwoDirectionsResId: Int, |
| @@ -907,10 +949,16 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 907 | ButtonType.DPAD_RIGHT | 949 | ButtonType.DPAD_RIGHT |
| 908 | ) | 950 | ) |
| 909 | 951 | ||
| 952 | // Get the minimum and maximum coordinates of the screen where the button can be placed. | ||
| 953 | val min = windowSize.first | ||
| 954 | val max = windowSize.second | ||
| 955 | |||
| 910 | // The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay. | 956 | // The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay. |
| 911 | // These were set in the input overlay configuration menu. | 957 | // These were set in the input overlay configuration menu. |
| 912 | val drawableX = sPrefs.getFloat("${ButtonType.DPAD_UP}$orientation-X", 0f).toInt() | 958 | val drawableXPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}$orientation-X", 0f) |
| 913 | val drawableY = sPrefs.getFloat("${ButtonType.DPAD_UP}$orientation-Y", 0f).toInt() | 959 | val drawableYPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}$orientation-Y", 0f) |
| 960 | val drawableX = (drawableXPercent * max.x + min.x).toInt() | ||
| 961 | val drawableY = (drawableYPercent * max.y + min.y).toInt() | ||
| 914 | val width = overlayDrawable.width | 962 | val width = overlayDrawable.width |
| 915 | val height = overlayDrawable.height | 963 | val height = overlayDrawable.height |
| 916 | 964 | ||
| @@ -932,6 +980,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 932 | * Initializes an [InputOverlayDrawableJoystick] | 980 | * Initializes an [InputOverlayDrawableJoystick] |
| 933 | * | 981 | * |
| 934 | * @param context The current [Context] | 982 | * @param context The current [Context] |
| 983 | * @param windowSize The size of the window to draw the overlay on. | ||
| 935 | * @param resOuter Resource ID for the outer image of the joystick (the static image that shows the circular bounds). | 984 | * @param resOuter Resource ID for the outer image of the joystick (the static image that shows the circular bounds). |
| 936 | * @param defaultResInner Resource ID for the default inner image of the joystick (the one you actually move around). | 985 | * @param defaultResInner Resource ID for the default inner image of the joystick (the one you actually move around). |
| 937 | * @param pressedResInner Resource ID for the pressed inner image of the joystick. | 986 | * @param pressedResInner Resource ID for the pressed inner image of the joystick. |
| @@ -941,6 +990,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 941 | */ | 990 | */ |
| 942 | private fun initializeOverlayJoystick( | 991 | private fun initializeOverlayJoystick( |
| 943 | context: Context, | 992 | context: Context, |
| 993 | windowSize: Pair<Point, Point>, | ||
| 944 | resOuter: Int, | 994 | resOuter: Int, |
| 945 | defaultResInner: Int, | 995 | defaultResInner: Int, |
| 946 | pressedResInner: Int, | 996 | pressedResInner: Int, |
| @@ -964,10 +1014,16 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context | |||
| 964 | val bitmapInnerDefault = getBitmap(context, defaultResInner, 1.0f) | 1014 | val bitmapInnerDefault = getBitmap(context, defaultResInner, 1.0f) |
| 965 | val bitmapInnerPressed = getBitmap(context, pressedResInner, 1.0f) | 1015 | val bitmapInnerPressed = getBitmap(context, pressedResInner, 1.0f) |
| 966 | 1016 | ||
| 1017 | // Get the minimum and maximum coordinates of the screen where the button can be placed. | ||
| 1018 | val min = windowSize.first | ||
| 1019 | val max = windowSize.second | ||
| 1020 | |||
| 967 | // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. | 1021 | // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. |
| 968 | // These were set in the input overlay configuration menu. | 1022 | // These were set in the input overlay configuration menu. |
| 969 | val drawableX = sPrefs.getFloat("$button$orientation-X", 0f).toInt() | 1023 | val drawableXPercent = sPrefs.getFloat("$button$orientation-X", 0f) |
| 970 | val drawableY = sPrefs.getFloat("$button$orientation-Y", 0f).toInt() | 1024 | val drawableYPercent = sPrefs.getFloat("$button$orientation-Y", 0f) |
| 1025 | val drawableX = (drawableXPercent * max.x + min.x).toInt() | ||
| 1026 | val drawableY = (drawableYPercent * max.y + min.y).toInt() | ||
| 971 | val outerScale = 1.66f | 1027 | val outerScale = 1.66f |
| 972 | 1028 | ||
| 973 | // Now set the bounds for the InputOverlayDrawableJoystick. | 1029 | // Now set the bounds for the InputOverlayDrawableJoystick. |