From 89cab445d44d176d57b431219218b073a2fd351c Mon Sep 17 00:00:00 2001 From: vitor-k Date: Fri, 25 Oct 2019 20:21:10 -0300 Subject: [PATCH 1/4] Implementation of screen rotation without use of additional layouts. This is based on what was done using additional layouts, but modified to have a variable to control rotation and making it so Single Screen Layout behaves like Upright Single would, and Default Layout behaves like Upright Double would, when the new variable is used. Large Layout and Side Layout currently ignore the new variable. New variable still currently doesn't have a hotkey. --- src/citra/config.cpp | 1 + src/citra/default_ini.h | 4 + src/citra_qt/configuration/config.cpp | 2 + .../configuration/configure_enhancements.cpp | 2 + .../configuration/configure_enhancements.ui | 7 + src/citra_qt/main.cpp | 8 + src/citra_qt/main.h | 1 + src/citra_qt/main.ui | 9 + src/core/frontend/emu_window.cpp | 17 +- src/core/frontend/framebuffer_layout.cpp | 168 ++++++++++++----- src/core/frontend/framebuffer_layout.h | 9 +- src/core/settings.h | 1 + .../renderer_opengl/renderer_opengl.cpp | 172 ++++++++++++++---- .../renderer_opengl/renderer_opengl.h | 3 + 14 files changed, 317 insertions(+), 87 deletions(-) diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 072568827..b2c878ddf 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -151,6 +151,7 @@ void Config::ReadValues() { Settings::values.layout_option = static_cast(sdl2_config->GetInteger("Layout", "layout_option", 0)); Settings::values.swap_screen = sdl2_config->GetBoolean("Layout", "swap_screen", false); + Settings::values.upright_screen = sdl2_config->GetBoolean("Layout", "upright_screen", false); Settings::values.custom_layout = sdl2_config->GetBoolean("Layout", "custom_layout", false); Settings::values.custom_top_left = static_cast(sdl2_config->GetInteger("Layout", "custom_top_left", 0)); diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index ca154c4a7..9c441e354 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -183,6 +183,10 @@ custom_bottom_bottom = # 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent swap_screen = +# Toggle upright orientation, for book style games. +# 0 (default): Off, 1: On +upright_screen = + # Dumps textures as PNG to dump/textures/[Title ID]/. # 0 (default): Off, 1: On dump_textures = diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 7601d485b..662385086 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -296,6 +296,7 @@ void Config::ReadLayoutValues() { Settings::values.layout_option = static_cast(ReadSetting(QStringLiteral("layout_option")).toInt()); Settings::values.swap_screen = ReadSetting(QStringLiteral("swap_screen"), false).toBool(); + Settings::values.upright_screen = ReadSetting(QStringLiteral("upright_screen"), false).toBool(); Settings::values.custom_layout = ReadSetting(QStringLiteral("custom_layout"), false).toBool(); Settings::values.custom_top_left = ReadSetting(QStringLiteral("custom_top_left"), 0).toInt(); Settings::values.custom_top_top = ReadSetting(QStringLiteral("custom_top_top"), 0).toInt(); @@ -765,6 +766,7 @@ void Config::SaveLayoutValues() { WriteSetting(QStringLiteral("filter_mode"), Settings::values.filter_mode, true); WriteSetting(QStringLiteral("layout_option"), static_cast(Settings::values.layout_option)); WriteSetting(QStringLiteral("swap_screen"), Settings::values.swap_screen, false); + WriteSetting(QStringLiteral("upright_screen"), Settings::values.upright_screen, false); WriteSetting(QStringLiteral("custom_layout"), Settings::values.custom_layout, false); WriteSetting(QStringLiteral("custom_top_left"), Settings::values.custom_top_left, 0); WriteSetting(QStringLiteral("custom_top_top"), Settings::values.custom_top_top, 0); diff --git a/src/citra_qt/configuration/configure_enhancements.cpp b/src/citra_qt/configuration/configure_enhancements.cpp index 4067d64bc..3619adb34 100644 --- a/src/citra_qt/configuration/configure_enhancements.cpp +++ b/src/citra_qt/configuration/configure_enhancements.cpp @@ -53,6 +53,7 @@ void ConfigureEnhancements::SetConfiguration() { ui->layout_combobox->setCurrentIndex(static_cast(Settings::values.layout_option)); ui->swap_screen->setChecked(Settings::values.swap_screen); ui->toggle_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache); + ui->upright_screen->setChecked(Settings::values.upright_screen); ui->toggle_dump_textures->setChecked(Settings::values.dump_textures); ui->toggle_custom_textures->setChecked(Settings::values.custom_textures); ui->toggle_preload_textures->setChecked(Settings::values.preload_textures); @@ -101,6 +102,7 @@ void ConfigureEnhancements::ApplyConfiguration() { static_cast(ui->layout_combobox->currentIndex()); Settings::values.swap_screen = ui->swap_screen->isChecked(); Settings::values.use_disk_shader_cache = ui->toggle_disk_shader_cache->isChecked(); + Settings::values.upright_screen = ui->upright_screen->isChecked(); Settings::values.dump_textures = ui->toggle_dump_textures->isChecked(); Settings::values.custom_textures = ui->toggle_custom_textures->isChecked(); Settings::values.preload_textures = ui->toggle_preload_textures->isChecked(); diff --git a/src/citra_qt/configuration/configure_enhancements.ui b/src/citra_qt/configuration/configure_enhancements.ui index 26c65ed59..289c1178e 100644 --- a/src/citra_qt/configuration/configure_enhancements.ui +++ b/src/citra_qt/configuration/configure_enhancements.ui @@ -239,6 +239,13 @@ + + + + Rotate Screens Upright + + + diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index dd56f4b13..457de1b60 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -618,6 +618,8 @@ void GMainWindow::ConnectMenuEvents() { &GMainWindow::ChangeScreenLayout); connect(ui.action_Screen_Layout_Swap_Screens, &QAction::triggered, this, &GMainWindow::OnSwapScreens); + connect(ui.action_Screen_Layout_Upright_Screens, &QAction::triggered, this, + &GMainWindow::OnRotateScreens); // Movie connect(ui.action_Record_Movie, &QAction::triggered, this, &GMainWindow::OnRecordMovie); @@ -1435,6 +1437,11 @@ void GMainWindow::OnSwapScreens() { Settings::Apply(); } +void GMainWindow::OnRotateScreens() { + Settings::values.upright_screen = ui.action_Screen_Layout_Upright_Screens->isChecked(); + Settings::Apply(); +} + void GMainWindow::OnCheats() { CheatDialog cheat_dialog(this); cheat_dialog.exec(); @@ -2032,6 +2039,7 @@ void GMainWindow::SyncMenuUISettings() { ui.action_Screen_Layout_Side_by_Side->setChecked(Settings::values.layout_option == Settings::LayoutOption::SideScreen); ui.action_Screen_Layout_Swap_Screens->setChecked(Settings::values.swap_screen); + ui.action_Screen_Layout_Upright_Screens->setChecked(Settings::values.upright_screen); } void GMainWindow::RetranslateStatusBar() { diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index 0fa04f5b8..7ec4fa185 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -187,6 +187,7 @@ private slots: void ChangeScreenLayout(); void ToggleScreenLayout(); void OnSwapScreens(); + void OnRotateScreens(); void OnCheats(); void ShowFullscreen(); void HideFullscreen(); diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui index 60dff0417..c950fefd5 100644 --- a/src/citra_qt/main.ui +++ b/src/citra_qt/main.ui @@ -110,6 +110,7 @@ + @@ -425,6 +426,14 @@ Swap Screens + + + true + + + Rotate Upright + + Check for Updates diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index f393e4c76..23c33f627 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -118,6 +118,11 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { static_cast(framebuffer_y - framebuffer_layout.bottom_screen.top) / (framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top); + if (!framebuffer_layout.is_rotated) { + std::swap(touch_state->touch_x, touch_state->touch_y); + touch_state->touch_x = 1.f - touch_state->touch_x; + } + touch_state->touch_pressed = true; } @@ -145,17 +150,21 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) } else { switch (Settings::values.layout_option) { case Settings::LayoutOption::SingleScreen: - layout = Layout::SingleFrameLayout(width, height, Settings::values.swap_screen); + layout = Layout::SingleFrameLayout(width, height, Settings::values.swap_screen, + Settings::values.upright_screen); break; case Settings::LayoutOption::LargeScreen: - layout = Layout::LargeFrameLayout(width, height, Settings::values.swap_screen); + layout = Layout::LargeFrameLayout(width, height, Settings::values.swap_screen, + Settings::values.upright_screen); break; case Settings::LayoutOption::SideScreen: - layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen); + layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen, + Settings::values.upright_screen); break; case Settings::LayoutOption::Default: default: - layout = Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen); + layout = Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen, + Settings::values.upright_screen); break; } } diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index c66a4bc95..2c6c9cdce 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -15,9 +15,17 @@ static const float TOP_SCREEN_ASPECT_RATIO = static_cast(Core::kScreenTopHeight) / Core::kScreenTopWidth; static const float BOT_SCREEN_ASPECT_RATIO = static_cast(Core::kScreenBottomHeight) / Core::kScreenBottomWidth; +static const float TOP_SCREEN_UPRIGHT_ASPECT_RATIO = + static_cast(Core::kScreenTopWidth) / Core::kScreenTopHeight; +static const float BOT_SCREEN_UPRIGHT_ASPECT_RATIO = + static_cast(Core::kScreenBottomWidth) / Core::kScreenBottomHeight; u32 FramebufferLayout::GetScalingRatio() const { - return static_cast(((top_screen.GetWidth() - 1) / Core::kScreenTopWidth) + 1); + if (is_rotated) { + return static_cast(((top_screen.GetWidth() - 1) / Core::kScreenTopWidth) + 1); + } else { + return static_cast(((top_screen.GetWidth() - 1) / Core::kScreenTopHeight) + 1); + } } // Finds the largest size subrectangle contained in window area that is confined to the aspect ratio @@ -30,57 +38,108 @@ static Common::Rectangle maxRectangle(Common::Rectangle window_area, static_cast(std::round(scale * screen_aspect_ratio))}; } -FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool swapped) { +FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool swapped, bool upright) { ASSERT(width > 0); ASSERT(height > 0); - FramebufferLayout res{width, height, true, true, {}, {}}; - // Default layout gives equal screen sizes to the top and bottom screen - Common::Rectangle screen_window_area{0, 0, width, height / 2}; - Common::Rectangle top_screen = maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO); - Common::Rectangle bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); + FramebufferLayout res{width, height, true, true, {}, {}, !upright}; + Common::Rectangle screen_window_area; + Common::Rectangle top_screen; + Common::Rectangle bot_screen; + float emulation_aspect_ratio; + if (upright) { + // Default layout gives equal screen sizes to the top and bottom screen + screen_window_area = {0, 0, width / 2, height}; + top_screen = maxRectangle(screen_window_area, TOP_SCREEN_UPRIGHT_ASPECT_RATIO); + bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_UPRIGHT_ASPECT_RATIO); + // both screens width are taken into account by dividing by 2 + emulation_aspect_ratio = TOP_SCREEN_UPRIGHT_ASPECT_RATIO / 2; + } else { + // Default layout gives equal screen sizes to the top and bottom screen + screen_window_area = {0, 0, width, height / 2}; + top_screen = maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO); + bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); + // both screens height are taken into account by multiplying by 2 + emulation_aspect_ratio = TOP_SCREEN_ASPECT_RATIO * 2; + } float window_aspect_ratio = static_cast(height) / width; - // both screens height are taken into account by multiplying by 2 - float emulation_aspect_ratio = TOP_SCREEN_ASPECT_RATIO * 2; if (window_aspect_ratio < emulation_aspect_ratio) { - // Apply borders to the left and right sides of the window. - top_screen = - top_screen.TranslateX((screen_window_area.GetWidth() - top_screen.GetWidth()) / 2); - bot_screen = - bot_screen.TranslateX((screen_window_area.GetWidth() - bot_screen.GetWidth()) / 2); + // Window is wider than the emulation content => apply borders to the right and left sides + if (upright) { + // Recalculate the bottom screen to account for the height difference between right and + // left + screen_window_area = {0, 0, top_screen.GetWidth(), height}; + bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_UPRIGHT_ASPECT_RATIO); + bot_screen = + bot_screen.TranslateY((top_screen.GetHeight() - bot_screen.GetHeight()) / 2); + if (swapped) { + bot_screen = bot_screen.TranslateX(width / 2 - bot_screen.GetWidth()); + } else { + top_screen = top_screen.TranslateX(width / 2 - top_screen.GetWidth()); + } + } else { + top_screen = + top_screen.TranslateX((screen_window_area.GetWidth() - top_screen.GetWidth()) / 2); + bot_screen = + bot_screen.TranslateX((screen_window_area.GetWidth() - bot_screen.GetWidth()) / 2); + } } else { // Window is narrower than the emulation content => apply borders to the top and bottom - // Recalculate the bottom screen to account for the width difference between top and bottom - screen_window_area = {0, 0, width, top_screen.GetHeight()}; - bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); - bot_screen = bot_screen.TranslateX((top_screen.GetWidth() - bot_screen.GetWidth()) / 2); - if (swapped) { - bot_screen = bot_screen.TranslateY(height / 2 - bot_screen.GetHeight()); + if (upright) { + top_screen = top_screen.TranslateY( + (screen_window_area.GetHeight() - top_screen.GetHeight()) / 2); + bot_screen = bot_screen.TranslateY( + (screen_window_area.GetHeight() - bot_screen.GetHeight()) / 2); } else { - top_screen = top_screen.TranslateY(height / 2 - top_screen.GetHeight()); + // Recalculate the bottom screen to account for the width difference between top and + // bottom + screen_window_area = {0, 0, width, top_screen.GetHeight()}; + bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); + bot_screen = bot_screen.TranslateX((top_screen.GetWidth() - bot_screen.GetWidth()) / 2); + if (swapped) { + bot_screen = bot_screen.TranslateY(height / 2 - bot_screen.GetHeight()); + } else { + top_screen = top_screen.TranslateY(height / 2 - top_screen.GetHeight()); + } } } - // Move the top screen to the bottom if we are swapped. - res.top_screen = swapped ? top_screen.TranslateY(height / 2) : top_screen; - res.bottom_screen = swapped ? bot_screen : bot_screen.TranslateY(height / 2); + if (upright) { + // Move the top screen to the right if we are swapped. + res.top_screen = swapped ? top_screen.TranslateX(width / 2) : top_screen; + res.bottom_screen = swapped ? bot_screen : bot_screen.TranslateX(width / 2); + } else { + // Move the top screen to the bottom if we are swapped. + res.top_screen = swapped ? top_screen.TranslateY(height / 2) : top_screen; + res.bottom_screen = swapped ? bot_screen : bot_screen.TranslateY(height / 2); + } return res; } -FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped) { +FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped, bool upright) { ASSERT(width > 0); ASSERT(height > 0); // The drawing code needs at least somewhat valid values for both screens // so just calculate them both even if the other isn't showing. - FramebufferLayout res{width, height, !swapped, swapped, {}, {}}; + FramebufferLayout res{width, height, !swapped, swapped, {}, {}, !upright}; Common::Rectangle screen_window_area{0, 0, width, height}; - Common::Rectangle top_screen = maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO); - Common::Rectangle bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); + Common::Rectangle top_screen; + Common::Rectangle bot_screen; + float emulation_aspect_ratio; + if (upright) { + top_screen = maxRectangle(screen_window_area, TOP_SCREEN_UPRIGHT_ASPECT_RATIO); + bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_UPRIGHT_ASPECT_RATIO); + emulation_aspect_ratio = + (swapped) ? BOT_SCREEN_UPRIGHT_ASPECT_RATIO : TOP_SCREEN_UPRIGHT_ASPECT_RATIO; + } else { + top_screen = maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO); + bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); + emulation_aspect_ratio = (swapped) ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO; + } float window_aspect_ratio = static_cast(height) / width; - float emulation_aspect_ratio = (swapped) ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO; if (window_aspect_ratio < emulation_aspect_ratio) { top_screen = @@ -96,11 +155,11 @@ FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped) { return res; } -FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped) { +FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped, bool upright) { ASSERT(width > 0); ASSERT(height > 0); - FramebufferLayout res{width, height, true, true, {}, {}}; + FramebufferLayout res{width, height, true, true, {}, {}, true}; // Split the window into two parts. Give 4x width to the main screen and 1x width to the small // To do that, find the total emulation box and maximize that based on window size float window_aspect_ratio = static_cast(height) / width; @@ -133,11 +192,11 @@ FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped) { return res; } -FramebufferLayout SideFrameLayout(u32 width, u32 height, bool swapped) { +FramebufferLayout SideFrameLayout(u32 width, u32 height, bool swapped, bool upright) { ASSERT(width > 0); ASSERT(height > 0); - FramebufferLayout res{width, height, true, true, {}, {}}; + FramebufferLayout res{width, height, true, true, {}, {}, true}; // Aspect ratio of both screens side by side const float emulation_aspect_ratio = static_cast(Core::kScreenTopHeight) / (Core::kScreenTopWidth + Core::kScreenBottomWidth); @@ -170,7 +229,7 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height) { ASSERT(width > 0); ASSERT(height > 0); - FramebufferLayout res{width, height, true, true, {}, {}}; + FramebufferLayout res{width, height, true, true, {}, {}, !Settings::values.upright_screen}; Common::Rectangle top_screen{ Settings::values.custom_top_left, Settings::values.custom_top_top, @@ -194,14 +253,25 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { int width, height; switch (Settings::values.layout_option) { case Settings::LayoutOption::SingleScreen: - if (Settings::values.swap_screen) { - width = Core::kScreenBottomWidth * res_scale; - height = Core::kScreenBottomHeight * res_scale; + if (Settings::values.upright_screen) { + if (Settings::values.swap_screen) { + width = Core::kScreenBottomHeight * res_scale; + height = Core::kScreenBottomWidth * res_scale; + } else { + width = Core::kScreenTopHeight * res_scale; + height = Core::kScreenTopWidth * res_scale; + } } else { - width = Core::kScreenTopWidth * res_scale; - height = Core::kScreenTopHeight * res_scale; + if (Settings::values.swap_screen) { + width = Core::kScreenBottomWidth * res_scale; + height = Core::kScreenBottomHeight * res_scale; + } else { + width = Core::kScreenTopWidth * res_scale; + height = Core::kScreenTopHeight * res_scale; + } } - layout = SingleFrameLayout(width, height, Settings::values.swap_screen); + layout = SingleFrameLayout(width, height, Settings::values.swap_screen, + Settings::values.upright_screen); break; case Settings::LayoutOption::LargeScreen: if (Settings::values.swap_screen) { @@ -211,18 +281,26 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { width = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 4) * res_scale; height = Core::kScreenTopHeight * res_scale; } - layout = LargeFrameLayout(width, height, Settings::values.swap_screen); + layout = LargeFrameLayout(width, height, Settings::values.swap_screen, + Settings::values.upright_screen); break; case Settings::LayoutOption::SideScreen: width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; height = Core::kScreenTopHeight * res_scale; - layout = SideFrameLayout(width, height, Settings::values.swap_screen); + layout = SideFrameLayout(width, height, Settings::values.swap_screen, + Settings::values.upright_screen); break; case Settings::LayoutOption::Default: default: - width = Core::kScreenTopWidth * res_scale; - height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; - layout = DefaultFrameLayout(width, height, Settings::values.swap_screen); + if (Settings::values.upright_screen) { + width = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; + height = Core::kScreenTopWidth * res_scale; + } else { + width = Core::kScreenTopWidth * res_scale; + height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; + } + layout = DefaultFrameLayout(width, height, Settings::values.swap_screen, + Settings::values.upright_screen); break; } } diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index c565d33b8..5feb16f64 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -16,6 +16,7 @@ struct FramebufferLayout { bool bottom_screen_enabled; Common::Rectangle top_screen; Common::Rectangle bottom_screen; + bool is_rotated = true; /** * Returns the ration of pixel size of the top screen, compared to the native size of the 3DS @@ -31,7 +32,7 @@ struct FramebufferLayout { * @param is_swapped if true, the bottom screen will be displayed above the top screen * @return Newly created FramebufferLayout object with default screen regions initialized */ -FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped); +FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, bool upright); /** * Factory method for constructing a FramebufferLayout with only the top or bottom screen @@ -40,7 +41,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped); * @param is_swapped if true, the bottom screen will be displayed (and the top won't be displayed) * @return Newly created FramebufferLayout object with default screen regions initialized */ -FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool is_swapped); +FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool is_swapped, bool upright); /** * Factory method for constructing a Frame with the a 4x size Top screen with a 1x size bottom @@ -51,7 +52,7 @@ FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool is_swapped); * @param is_swapped if true, the bottom screen will be the large display * @return Newly created FramebufferLayout object with default screen regions initialized */ -FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool is_swapped); +FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool is_swapped, bool upright); /** * Factory method for constructing a Frame with the Top screen and bottom @@ -62,7 +63,7 @@ FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool is_swapped); * @param is_swapped if true, the bottom screen will be the left display * @return Newly created FramebufferLayout object with default screen regions initialized */ -FramebufferLayout SideFrameLayout(u32 width, u32 height, bool is_swapped); +FramebufferLayout SideFrameLayout(u32 width, u32 height, bool is_swapped, bool upright); /** * Factory method for constructing a custom FramebufferLayout diff --git a/src/core/settings.h b/src/core/settings.h index 2d139e1b2..78b11912c 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -150,6 +150,7 @@ struct Values { LayoutOption layout_option; bool swap_screen; + bool upright_screen; bool custom_layout; u16 custom_top_left; u16 custom_top_top; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index b1fe38a7e..5046895e0 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -781,6 +781,35 @@ void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, floa state.Apply(); } +void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, + float h) { + const auto& texcoords = screen_info.display_texcoords; + + const std::array vertices = {{ + ScreenRectVertex(x, y, texcoords.bottom, texcoords.right), + ScreenRectVertex(x + w, y, texcoords.top, texcoords.right), + ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left), + ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left), + }}; + + u16 scale_factor = VideoCore::GetResolutionScaleFactor(); + glUniform4f(uniform_i_resolution, screen_info.texture.width * scale_factor, + screen_info.texture.height * scale_factor, + 1.0 / (screen_info.texture.width * scale_factor), + 1.0 / (screen_info.texture.height * scale_factor)); + glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h); + state.texture_units[0].texture_2d = screen_info.display_texture; + state.texture_units[0].sampler = filter_sampler.handle; + state.Apply(); + + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + state.texture_units[0].texture_2d = 0; + state.texture_units[0].sampler = 0; + state.Apply(); +} + /** * Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD * rotation. @@ -819,6 +848,40 @@ void RendererOpenGL::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info state.Apply(); } +void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l, + const ScreenInfo& screen_info_r, float x, float y, + float w, float h) { + const auto& texcoords = screen_info_l.display_texcoords; + + const std::array vertices = {{ + ScreenRectVertex(x, y, texcoords.bottom, texcoords.right), + ScreenRectVertex(x + w, y, texcoords.top, texcoords.right), + ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left), + ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left), + }}; + + u16 scale_factor = VideoCore::GetResolutionScaleFactor(); + glUniform4f(uniform_i_resolution, screen_info_l.texture.width * scale_factor, + screen_info_l.texture.height * scale_factor, + 1.0 / (screen_info_l.texture.width * scale_factor), + 1.0 / (screen_info_l.texture.height * scale_factor)); + glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h); + state.texture_units[0].texture_2d = screen_info_l.display_texture; + state.texture_units[1].texture_2d = screen_info_r.display_texture; + state.texture_units[0].sampler = filter_sampler.handle; + state.texture_units[1].sampler = filter_sampler.handle; + state.Apply(); + + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + state.texture_units[0].texture_2d = 0; + state.texture_units[1].texture_2d = 0; + state.texture_units[0].sampler = 0; + state.texture_units[1].sampler = 0; + state.Apply(); +} + /** * Draws the emulated screens to the emulator window. */ @@ -866,44 +929,85 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout) { glUniform1i(uniform_layer, 0); if (layout.top_screen_enabled) { - if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { - DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left, (float)top_screen.top, - (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); - } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { - DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2, - (float)top_screen.top, (float)top_screen.GetWidth() / 2, - (float)top_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated(screen_infos[1], - ((float)top_screen.left / 2) + ((float)layout.width / 2), - (float)top_screen.top, (float)top_screen.GetWidth() / 2, - (float)top_screen.GetHeight()); - } else if (stereo_single_screen) { - DrawSingleScreenStereoRotated(screen_infos[0], screen_infos[1], (float)top_screen.left, - (float)top_screen.top, (float)top_screen.GetWidth(), - (float)top_screen.GetHeight()); + if (layout.is_rotated) { + if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { + DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left, + (float)top_screen.top, (float)top_screen.GetWidth(), + (float)top_screen.GetHeight()); + } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { + DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2, + (float)top_screen.top, (float)top_screen.GetWidth() / 2, + (float)top_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreenRotated(screen_infos[1], + ((float)top_screen.left / 2) + ((float)layout.width / 2), + (float)top_screen.top, (float)top_screen.GetWidth() / 2, + (float)top_screen.GetHeight()); + } else if (stereo_single_screen) { + DrawSingleScreenStereoRotated( + screen_infos[0], screen_infos[1], (float)top_screen.left, (float)top_screen.top, + (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); + } + } else { + if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { + DrawSingleScreen(screen_infos[0], (float)top_screen.left, (float)top_screen.top, + (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); + } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { + DrawSingleScreen(screen_infos[0], (float)top_screen.left / 2, (float)top_screen.top, + (float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreen(screen_infos[1], + ((float)top_screen.left / 2) + ((float)layout.width / 2), + (float)top_screen.top, (float)top_screen.GetWidth() / 2, + (float)top_screen.GetHeight()); + } else if (stereo_single_screen) { + DrawSingleScreenStereo(screen_infos[0], screen_infos[1], (float)top_screen.left, + (float)top_screen.top, (float)top_screen.GetWidth(), + (float)top_screen.GetHeight()); + } } } glUniform1i(uniform_layer, 0); if (layout.bottom_screen_enabled) { - if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { - DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left, - (float)bottom_screen.top, (float)bottom_screen.GetWidth(), - (float)bottom_screen.GetHeight()); - } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { - DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left / 2, - (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, - (float)bottom_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated(screen_infos[2], - ((float)bottom_screen.left / 2) + ((float)layout.width / 2), - (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, - (float)bottom_screen.GetHeight()); - } else if (stereo_single_screen) { - DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], - (float)bottom_screen.left, (float)bottom_screen.top, - (float)bottom_screen.GetWidth(), - (float)bottom_screen.GetHeight()); + if (layout.is_rotated) { + if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { + DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left, + (float)bottom_screen.top, (float)bottom_screen.GetWidth(), + (float)bottom_screen.GetHeight()); + } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { + DrawSingleScreenRotated( + screen_infos[2], (float)bottom_screen.left / 2, (float)bottom_screen.top, + (float)bottom_screen.GetWidth() / 2, (float)bottom_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreenRotated( + screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2), + (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, + (float)bottom_screen.GetHeight()); + } else if (stereo_single_screen) { + DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], + (float)bottom_screen.left, (float)bottom_screen.top, + (float)bottom_screen.GetWidth(), + (float)bottom_screen.GetHeight()); + } + } else { + if (Settings::values.render_3d == Settings::StereoRenderOption::Off) { + DrawSingleScreen(screen_infos[2], (float)bottom_screen.left, + (float)bottom_screen.top, (float)bottom_screen.GetWidth(), + (float)bottom_screen.GetHeight()); + } else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { + DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2, + (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, + (float)bottom_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreen(screen_infos[2], + ((float)bottom_screen.left / 2) + ((float)layout.width / 2), + (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, + (float)bottom_screen.GetHeight()); + } else if (stereo_single_screen) { + DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left, + (float)bottom_screen.top, (float)bottom_screen.GetWidth(), + (float)bottom_screen.GetHeight()); + } } } } diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 465ebfb6e..96df7f8ac 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -77,9 +77,12 @@ private: const GPU::Regs::FramebufferConfig& framebuffer); void DrawScreens(const Layout::FramebufferLayout& layout); void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h); + void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h); void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l, const ScreenInfo& screen_info_r, float x, float y, float w, float h); + void DrawSingleScreenStereo(const ScreenInfo& screen_info_l, const ScreenInfo& screen_info_r, + float x, float y, float w, float h); void UpdateFramerate(); // Loads framebuffer from emulated memory into the display information structure From be88d2a59aa2d61a44264e468e7269da36f83f5c Mon Sep 17 00:00:00 2001 From: Vitor Kiguchi Date: Wed, 8 Jan 2020 17:57:41 -0300 Subject: [PATCH 2/4] implement upright orientation for side and large frame layouts --- src/core/frontend/framebuffer_layout.cpp | 114 +++++++++++++++++------ 1 file changed, 85 insertions(+), 29 deletions(-) diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 2c6c9cdce..cb7993271 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -159,17 +159,38 @@ FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped, bool upr ASSERT(width > 0); ASSERT(height > 0); - FramebufferLayout res{width, height, true, true, {}, {}, true}; + FramebufferLayout res{width, height, true, true, {}, {}, !upright}; // Split the window into two parts. Give 4x width to the main screen and 1x width to the small // To do that, find the total emulation box and maximize that based on window size float window_aspect_ratio = static_cast(height) / width; - float emulation_aspect_ratio = - swapped ? Core::kScreenBottomHeight * 4 / - (Core::kScreenBottomWidth * 4.0f + Core::kScreenTopWidth) - : Core::kScreenTopHeight * 4 / - (Core::kScreenTopWidth * 4.0f + Core::kScreenBottomWidth); - float large_screen_aspect_ratio = swapped ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO; - float small_screen_aspect_ratio = swapped ? TOP_SCREEN_ASPECT_RATIO : BOT_SCREEN_ASPECT_RATIO; + float emulation_aspect_ratio; + float large_screen_aspect_ratio; + float small_screen_aspect_ratio; + if (upright) { + if (swapped) { + emulation_aspect_ratio = (Core::kScreenBottomWidth * 4.0f + Core::kScreenTopWidth) / + (Core::kScreenBottomHeight * 4); + large_screen_aspect_ratio = BOT_SCREEN_UPRIGHT_ASPECT_RATIO; + small_screen_aspect_ratio = TOP_SCREEN_UPRIGHT_ASPECT_RATIO; + } else { + emulation_aspect_ratio = (Core::kScreenTopWidth * 4.0f + Core::kScreenBottomWidth) / + (Core::kScreenTopHeight * 4); + large_screen_aspect_ratio = TOP_SCREEN_UPRIGHT_ASPECT_RATIO; + small_screen_aspect_ratio = BOT_SCREEN_UPRIGHT_ASPECT_RATIO; + } + } else { + if (swapped) { + emulation_aspect_ratio = Core::kScreenBottomHeight * 4 / + (Core::kScreenBottomWidth * 4.0f + Core::kScreenTopWidth); + large_screen_aspect_ratio = BOT_SCREEN_ASPECT_RATIO; + small_screen_aspect_ratio = TOP_SCREEN_ASPECT_RATIO; + } else { + emulation_aspect_ratio = Core::kScreenTopHeight * 4 / + (Core::kScreenTopWidth * 4.0f + Core::kScreenBottomWidth); + large_screen_aspect_ratio = TOP_SCREEN_ASPECT_RATIO; + small_screen_aspect_ratio = BOT_SCREEN_ASPECT_RATIO; + } + } Common::Rectangle screen_window_area{0, 0, width, height}; Common::Rectangle total_rect = maxRectangle(screen_window_area, emulation_aspect_ratio); @@ -178,15 +199,20 @@ FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped, bool upr Common::Rectangle small_screen = maxRectangle(fourth_size_rect, small_screen_aspect_ratio); if (window_aspect_ratio < emulation_aspect_ratio) { - large_screen = - large_screen.TranslateX((screen_window_area.GetWidth() - total_rect.GetWidth()) / 2); + large_screen = large_screen.TranslateX((width - total_rect.GetWidth()) / 2); } else { large_screen = large_screen.TranslateY((height - total_rect.GetHeight()) / 2); } - // Shift the small screen to the bottom right corner - small_screen = - small_screen.TranslateX(large_screen.right) - .TranslateY(large_screen.GetHeight() + large_screen.top - small_screen.GetHeight()); + if (upright) { + large_screen = large_screen.TranslateY(small_screen.GetHeight()); + small_screen = small_screen.TranslateX(large_screen.right - small_screen.GetWidth()) + .TranslateY(large_screen.top - small_screen.GetHeight()); + } else { + // Shift the small screen to the bottom right corner + small_screen = + small_screen.TranslateX(large_screen.right) + .TranslateY(large_screen.GetHeight() + large_screen.top - small_screen.GetHeight()); + } res.top_screen = swapped ? small_screen : large_screen; res.bottom_screen = swapped ? large_screen : small_screen; return res; @@ -196,17 +222,26 @@ FramebufferLayout SideFrameLayout(u32 width, u32 height, bool swapped, bool upri ASSERT(width > 0); ASSERT(height > 0); - FramebufferLayout res{width, height, true, true, {}, {}, true}; + FramebufferLayout res{width, height, true, true, {}, {}, !upright}; + // Aspect ratio of both screens side by side - const float emulation_aspect_ratio = static_cast(Core::kScreenTopHeight) / - (Core::kScreenTopWidth + Core::kScreenBottomWidth); + float emulation_aspect_ratio = + upright ? static_cast(Core::kScreenTopWidth + Core::kScreenBottomWidth) / + Core::kScreenTopHeight + : static_cast(Core::kScreenTopHeight) / + (Core::kScreenTopWidth + Core::kScreenBottomWidth); + float window_aspect_ratio = static_cast(height) / width; Common::Rectangle screen_window_area{0, 0, width, height}; // Find largest Rectangle that can fit in the window size with the given aspect ratio Common::Rectangle screen_rect = maxRectangle(screen_window_area, emulation_aspect_ratio); // Find sizes of top and bottom screen - Common::Rectangle top_screen = maxRectangle(screen_rect, TOP_SCREEN_ASPECT_RATIO); - Common::Rectangle bot_screen = maxRectangle(screen_rect, BOT_SCREEN_ASPECT_RATIO); + Common::Rectangle top_screen = + upright ? maxRectangle(screen_rect, TOP_SCREEN_UPRIGHT_ASPECT_RATIO) + : maxRectangle(screen_rect, TOP_SCREEN_ASPECT_RATIO); + Common::Rectangle bot_screen = + upright ? maxRectangle(screen_rect, BOT_SCREEN_UPRIGHT_ASPECT_RATIO) + : maxRectangle(screen_rect, BOT_SCREEN_ASPECT_RATIO); if (window_aspect_ratio < emulation_aspect_ratio) { // Apply borders to the left and right sides of the window. @@ -219,9 +254,15 @@ FramebufferLayout SideFrameLayout(u32 width, u32 height, bool swapped, bool upri top_screen = top_screen.TranslateY(shift_vertical); bot_screen = bot_screen.TranslateY(shift_vertical); } - // Move the top screen to the right if we are swapped. - res.top_screen = swapped ? top_screen.TranslateX(bot_screen.GetWidth()) : top_screen; - res.bottom_screen = swapped ? bot_screen : bot_screen.TranslateX(top_screen.GetWidth()); + if (upright) { + // Leave the top screen at the top if we are swapped. + res.top_screen = swapped ? top_screen : top_screen.TranslateY(bot_screen.GetHeight()); + res.bottom_screen = swapped ? bot_screen.TranslateY(top_screen.GetHeight()) : bot_screen; + } else { + // Move the top screen to the right if we are swapped. + res.top_screen = swapped ? top_screen.TranslateX(bot_screen.GetWidth()) : top_screen; + res.bottom_screen = swapped ? bot_screen : bot_screen.TranslateX(top_screen.GetWidth()); + } return res; } @@ -274,19 +315,34 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { Settings::values.upright_screen); break; case Settings::LayoutOption::LargeScreen: - if (Settings::values.swap_screen) { - width = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 4) * res_scale; - height = Core::kScreenBottomHeight * res_scale; + if (Settings::values.upright_screen) { + if (Settings::values.swap_screen) { + width = Core::kScreenBottomHeight * res_scale; + height = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 4) * res_scale; + } else { + width = Core::kScreenTopHeight * res_scale; + height = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 4) * res_scale; + } } else { - width = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 4) * res_scale; - height = Core::kScreenTopHeight * res_scale; + if (Settings::values.swap_screen) { + width = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 4) * res_scale; + height = Core::kScreenBottomHeight * res_scale; + } else { + width = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 4) * res_scale; + height = Core::kScreenTopHeight * res_scale; + } } layout = LargeFrameLayout(width, height, Settings::values.swap_screen, Settings::values.upright_screen); break; case Settings::LayoutOption::SideScreen: - width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; - height = Core::kScreenTopHeight * res_scale; + if (Settings::values.upright_screen) { + width = Core::kScreenTopHeight * res_scale; + height = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; + } else { + width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; + height = Core::kScreenTopHeight * res_scale; + } layout = SideFrameLayout(width, height, Settings::values.swap_screen, Settings::values.upright_screen); break; From 5eb9a5b3bcb5e070feb655207d4595afe2df7e3c Mon Sep 17 00:00:00 2001 From: Vitor Kiguchi Date: Wed, 8 Jan 2020 18:33:37 -0300 Subject: [PATCH 3/4] Set hotkey for screen rotation --- src/citra_qt/configuration/config.cpp | 3 ++- src/citra_qt/main.cpp | 5 +++++ src/citra_qt/main.ui | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 662385086..7c834088f 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -57,7 +57,7 @@ const std::array, Settings::NativeAnalog::NumAnalogs> Config: // This must be in alphabetical order according to action name as it must have the same order as // UISetting::values.shortcuts, which is alphabetically ordered. // clang-format off -const std::array default_hotkeys{ +const std::array default_hotkeys{ {{QStringLiteral("Advance Frame"), QStringLiteral("Main Window"), {QStringLiteral("\\"), Qt::ApplicationShortcut}}, {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::ApplicationShortcut}}, {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}}, @@ -70,6 +70,7 @@ const std::array default_hotkeys{ {QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WindowShortcut}}, {QStringLiteral("Remove Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F3"), Qt::ApplicationShortcut}}, {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, + {QStringLiteral("Rotate Screens Upright"), QStringLiteral("Main Window"), {QStringLiteral("F8"), Qt::WindowShortcut}}, {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}}, {QStringLiteral("Swap Screens"), QStringLiteral("Main Window"), {QStringLiteral("F9"), Qt::WindowShortcut}}, {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}}, diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 457de1b60..863d0c5b8 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -410,6 +410,8 @@ void GMainWindow::InitializeHotkeys() { }); connect(hotkey_registry.GetHotkey("Main Window", "Swap Screens", render_window), &QShortcut::activated, ui.action_Screen_Layout_Swap_Screens, &QAction::trigger); + connect(hotkey_registry.GetHotkey("Main Window", "Rotate Screens Upright", render_window), + &QShortcut::activated, ui.action_Screen_Layout_Upright_Screens, &QAction::trigger); connect(hotkey_registry.GetHotkey("Main Window", "Toggle Screen Layout", render_window), &QShortcut::activated, this, &GMainWindow::ToggleScreenLayout); connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window), @@ -607,6 +609,9 @@ void GMainWindow::ConnectMenuEvents() { ui.action_Screen_Layout_Swap_Screens->setShortcut( hotkey_registry.GetHotkey("Main Window", "Swap Screens", this)->key()); ui.action_Screen_Layout_Swap_Screens->setShortcutContext(Qt::WidgetWithChildrenShortcut); + ui.action_Screen_Layout_Upright_Screens->setShortcut( + hotkey_registry.GetHotkey("Main Window", "Rotate Screens Upright", this)->key()); + ui.action_Screen_Layout_Upright_Screens->setShortcutContext(Qt::WidgetWithChildrenShortcut); connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen); connect(ui.action_Screen_Layout_Default, &QAction::triggered, this, &GMainWindow::ChangeScreenLayout); diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui index c950fefd5..89a279a1b 100644 --- a/src/citra_qt/main.ui +++ b/src/citra_qt/main.ui @@ -109,8 +109,8 @@ - + From c2179a1dd0e870187d7e5dc6b035203c5c8ccd43 Mon Sep 17 00:00:00 2001 From: Vitor Kiguchi Date: Sat, 18 Jan 2020 01:04:35 -0300 Subject: [PATCH 4/4] log the upright screen setting --- src/core/settings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 164ffaf73..a2c2d05fd 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -87,6 +87,7 @@ void LogSettings() { LogSetting("Stereoscopy_Factor3d", Settings::values.factor_3d); LogSetting("Layout_LayoutOption", static_cast(Settings::values.layout_option)); LogSetting("Layout_SwapScreen", Settings::values.swap_screen); + LogSetting("Layout_UprightScreen", Settings::values.upright_screen); LogSetting("Utility_DumpTextures", Settings::values.dump_textures); LogSetting("Utility_CustomTextures", Settings::values.custom_textures); LogSetting("Audio_EnableDspLle", Settings::values.enable_dsp_lle);