emu_window.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <cmath>
  6. #include "common/assert.h"
  7. #include "common/key_map.h"
  8. #include "emu_window.h"
  9. #include "video_core/video_core.h"
  10. void EmuWindow::ButtonPressed(Service::HID::PadState pad) {
  11. pad_state.hex |= pad.hex;
  12. }
  13. void EmuWindow::ButtonReleased(Service::HID::PadState pad) {
  14. pad_state.hex &= ~pad.hex;
  15. }
  16. void EmuWindow::CirclePadUpdated(float x, float y) {
  17. constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position
  18. // Make sure the coordinates are in the unit circle,
  19. // otherwise normalize it.
  20. float r = x * x + y * y;
  21. if (r > 1) {
  22. r = std::sqrt(r);
  23. x /= r;
  24. y /= r;
  25. }
  26. circle_pad_x = static_cast<s16>(x * MAX_CIRCLEPAD_POS);
  27. circle_pad_y = static_cast<s16>(y * MAX_CIRCLEPAD_POS);
  28. }
  29. /**
  30. * Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout
  31. * @param layout FramebufferLayout object describing the framebuffer size and screen positions
  32. * @param framebuffer_x Framebuffer x-coordinate to check
  33. * @param framebuffer_y Framebuffer y-coordinate to check
  34. * @return True if the coordinates are within the touchpad, otherwise false
  35. */
  36. static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigned framebuffer_x,
  37. unsigned framebuffer_y) {
  38. return (
  39. framebuffer_y >= layout.bottom_screen.top && framebuffer_y < layout.bottom_screen.bottom &&
  40. framebuffer_x >= layout.bottom_screen.left && framebuffer_x < layout.bottom_screen.right);
  41. }
  42. std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) {
  43. new_x = std::max(new_x, framebuffer_layout.bottom_screen.left);
  44. new_x = std::min(new_x, framebuffer_layout.bottom_screen.right - 1);
  45. new_y = std::max(new_y, framebuffer_layout.bottom_screen.top);
  46. new_y = std::min(new_y, framebuffer_layout.bottom_screen.bottom - 1);
  47. return std::make_tuple(new_x, new_y);
  48. }
  49. void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
  50. if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y))
  51. return;
  52. touch_x = VideoCore::kScreenBottomWidth *
  53. (framebuffer_x - framebuffer_layout.bottom_screen.left) /
  54. (framebuffer_layout.bottom_screen.right - framebuffer_layout.bottom_screen.left);
  55. touch_y = VideoCore::kScreenBottomHeight *
  56. (framebuffer_y - framebuffer_layout.bottom_screen.top) /
  57. (framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top);
  58. touch_pressed = true;
  59. pad_state.touch.Assign(1);
  60. }
  61. void EmuWindow::TouchReleased() {
  62. touch_pressed = false;
  63. touch_x = 0;
  64. touch_y = 0;
  65. pad_state.touch.Assign(0);
  66. }
  67. void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
  68. if (!touch_pressed)
  69. return;
  70. if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y))
  71. std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y);
  72. TouchPressed(framebuffer_x, framebuffer_y);
  73. }
  74. void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) {
  75. Layout::FramebufferLayout layout;
  76. switch (Settings::values.layout_option) {
  77. case Settings::LayoutOption::SingleScreen:
  78. layout = Layout::SingleFrameLayout(width, height, Settings::values.swap_screen);
  79. break;
  80. case Settings::LayoutOption::LargeScreen:
  81. layout = Layout::LargeFrameLayout(width, height, Settings::values.swap_screen);
  82. break;
  83. case Settings::LayoutOption::Default:
  84. default:
  85. layout = Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen);
  86. break;
  87. }
  88. NotifyFramebufferLayoutChanged(layout);
  89. }