mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Signed-off-by: elim <e_sliwka@tuta.io>
This commit is contained in:
		
							parent
							
								
									2d6aca4563
								
							
						
					
					
						commit
						0d516f6da5
					
				
					 9 changed files with 124 additions and 0 deletions
				
			
		|  | @ -187,6 +187,7 @@ filter_mode = | ||||||
| # 2: Large Screen Small Screen | # 2: Large Screen Small Screen | ||||||
| # 3: Side by Side | # 3: Side by Side | ||||||
| # 4: Separate Windows | # 4: Separate Windows | ||||||
|  | # 5: Hybrid Screen | ||||||
| layout_option = | layout_option = | ||||||
| 
 | 
 | ||||||
| # Toggle custom layout (using the settings below) on or off. | # Toggle custom layout (using the settings below) on or off. | ||||||
|  |  | ||||||
|  | @ -368,6 +368,11 @@ | ||||||
|              <string>Separate Windows</string> |              <string>Separate Windows</string> | ||||||
|             </property> |             </property> | ||||||
|            </item> |            </item> | ||||||
|  |            <item> | ||||||
|  |             <property name="text"> | ||||||
|  |              <string>Hybrid Screen</string> | ||||||
|  |             </property> | ||||||
|  |            </item> | ||||||
|           </widget> |           </widget> | ||||||
|          </item> |          </item> | ||||||
|         </layout> |         </layout> | ||||||
|  |  | ||||||
|  | @ -387,6 +387,7 @@ void GMainWindow::InitializeWidgets() { | ||||||
|     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Default); |     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Default); | ||||||
|     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Single_Screen); |     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Single_Screen); | ||||||
|     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Large_Screen); |     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Large_Screen); | ||||||
|  |     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Hybrid_Screen); | ||||||
|     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Side_by_Side); |     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Side_by_Side); | ||||||
|     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Separate_Windows); |     actionGroup_ScreenLayouts->addAction(ui->action_Screen_Layout_Separate_Windows); | ||||||
| } | } | ||||||
|  | @ -800,6 +801,7 @@ void GMainWindow::ConnectMenuEvents() { | ||||||
|     connect_menu(ui->action_Screen_Layout_Default, &GMainWindow::ChangeScreenLayout); |     connect_menu(ui->action_Screen_Layout_Default, &GMainWindow::ChangeScreenLayout); | ||||||
|     connect_menu(ui->action_Screen_Layout_Single_Screen, &GMainWindow::ChangeScreenLayout); |     connect_menu(ui->action_Screen_Layout_Single_Screen, &GMainWindow::ChangeScreenLayout); | ||||||
|     connect_menu(ui->action_Screen_Layout_Large_Screen, &GMainWindow::ChangeScreenLayout); |     connect_menu(ui->action_Screen_Layout_Large_Screen, &GMainWindow::ChangeScreenLayout); | ||||||
|  |     connect_menu(ui->action_Screen_Layout_Hybrid_Screen, &GMainWindow::ChangeScreenLayout); | ||||||
|     connect_menu(ui->action_Screen_Layout_Side_by_Side, &GMainWindow::ChangeScreenLayout); |     connect_menu(ui->action_Screen_Layout_Side_by_Side, &GMainWindow::ChangeScreenLayout); | ||||||
|     connect_menu(ui->action_Screen_Layout_Separate_Windows, &GMainWindow::ChangeScreenLayout); |     connect_menu(ui->action_Screen_Layout_Separate_Windows, &GMainWindow::ChangeScreenLayout); | ||||||
|     connect_menu(ui->action_Screen_Layout_Swap_Screens, &GMainWindow::OnSwapScreens); |     connect_menu(ui->action_Screen_Layout_Swap_Screens, &GMainWindow::OnSwapScreens); | ||||||
|  | @ -1883,6 +1885,8 @@ void GMainWindow::ChangeScreenLayout() { | ||||||
|         new_layout = Settings::LayoutOption::SingleScreen; |         new_layout = Settings::LayoutOption::SingleScreen; | ||||||
|     } else if (ui->action_Screen_Layout_Large_Screen->isChecked()) { |     } else if (ui->action_Screen_Layout_Large_Screen->isChecked()) { | ||||||
|         new_layout = Settings::LayoutOption::LargeScreen; |         new_layout = Settings::LayoutOption::LargeScreen; | ||||||
|  |     } else if (ui->action_Screen_Layout_Hybrid_Screen->isChecked()) { | ||||||
|  |         new_layout = Settings::LayoutOption::HybridScreen; | ||||||
|     } else if (ui->action_Screen_Layout_Side_by_Side->isChecked()) { |     } else if (ui->action_Screen_Layout_Side_by_Side->isChecked()) { | ||||||
|         new_layout = Settings::LayoutOption::SideScreen; |         new_layout = Settings::LayoutOption::SideScreen; | ||||||
|     } else if (ui->action_Screen_Layout_Separate_Windows->isChecked()) { |     } else if (ui->action_Screen_Layout_Separate_Windows->isChecked()) { | ||||||
|  | @ -1902,6 +1906,8 @@ void GMainWindow::ToggleScreenLayout() { | ||||||
|         case Settings::LayoutOption::SingleScreen: |         case Settings::LayoutOption::SingleScreen: | ||||||
|             return Settings::LayoutOption::LargeScreen; |             return Settings::LayoutOption::LargeScreen; | ||||||
|         case Settings::LayoutOption::LargeScreen: |         case Settings::LayoutOption::LargeScreen: | ||||||
|  |             return Settings::LayoutOption::HybridScreen; | ||||||
|  |         case Settings::LayoutOption::HybridScreen: | ||||||
|             return Settings::LayoutOption::SideScreen; |             return Settings::LayoutOption::SideScreen; | ||||||
|         case Settings::LayoutOption::SideScreen: |         case Settings::LayoutOption::SideScreen: | ||||||
|             return Settings::LayoutOption::SeparateWindows; |             return Settings::LayoutOption::SeparateWindows; | ||||||
|  | @ -2774,6 +2780,8 @@ void GMainWindow::SyncMenuUISettings() { | ||||||
|                                                        Settings::LayoutOption::SingleScreen); |                                                        Settings::LayoutOption::SingleScreen); | ||||||
|     ui->action_Screen_Layout_Large_Screen->setChecked(Settings::values.layout_option.GetValue() == |     ui->action_Screen_Layout_Large_Screen->setChecked(Settings::values.layout_option.GetValue() == | ||||||
|                                                       Settings::LayoutOption::LargeScreen); |                                                       Settings::LayoutOption::LargeScreen); | ||||||
|  |     ui->action_Screen_Layout_Hybrid_Screen->setChecked(Settings::values.layout_option.GetValue() == | ||||||
|  |                                                        Settings::LayoutOption::HybridScreen); | ||||||
|     ui->action_Screen_Layout_Side_by_Side->setChecked(Settings::values.layout_option.GetValue() == |     ui->action_Screen_Layout_Side_by_Side->setChecked(Settings::values.layout_option.GetValue() == | ||||||
|                                                       Settings::LayoutOption::SideScreen); |                                                       Settings::LayoutOption::SideScreen); | ||||||
|     ui->action_Screen_Layout_Separate_Windows->setChecked( |     ui->action_Screen_Layout_Separate_Windows->setChecked( | ||||||
|  |  | ||||||
|  | @ -134,6 +134,7 @@ | ||||||
|      <addaction name="action_Screen_Layout_Default"/> |      <addaction name="action_Screen_Layout_Default"/> | ||||||
|      <addaction name="action_Screen_Layout_Single_Screen"/> |      <addaction name="action_Screen_Layout_Single_Screen"/> | ||||||
|      <addaction name="action_Screen_Layout_Large_Screen"/> |      <addaction name="action_Screen_Layout_Large_Screen"/> | ||||||
|  |      <addaction name="action_Screen_Layout_Hybrid_Screen"/> | ||||||
|      <addaction name="action_Screen_Layout_Side_by_Side"/> |      <addaction name="action_Screen_Layout_Side_by_Side"/> | ||||||
|      <addaction name="action_Screen_Layout_Separate_Windows"/> |      <addaction name="action_Screen_Layout_Separate_Windows"/> | ||||||
|      <addaction name="separator"/> |      <addaction name="separator"/> | ||||||
|  | @ -504,6 +505,14 @@ | ||||||
|     <string>Large Screen</string> |     <string>Large Screen</string> | ||||||
|    </property> |    </property> | ||||||
|   </action> |   </action> | ||||||
|  |   <action name="action_Screen_Layout_Hybrid_Screen"> | ||||||
|  |    <property name="checkable"> | ||||||
|  |     <bool>true</bool> | ||||||
|  |    </property> | ||||||
|  |    <property name="text"> | ||||||
|  |     <string>Hybrid Screen</string> | ||||||
|  |    </property> | ||||||
|  |   </action> | ||||||
|   <action name="action_Screen_Layout_Side_by_Side"> |   <action name="action_Screen_Layout_Side_by_Side"> | ||||||
|    <property name="checkable"> |    <property name="checkable"> | ||||||
|     <bool>true</bool> |     <bool>true</bool> | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ enum class LayoutOption : u32 { | ||||||
| #ifndef ANDROID | #ifndef ANDROID | ||||||
|     SeparateWindows, |     SeparateWindows, | ||||||
| #endif | #endif | ||||||
|  |     HybridScreen, | ||||||
|     // Similiar to default, but better for mobile devices in portrait mode. Top screen in clamped to
 |     // Similiar to default, but better for mobile devices in portrait mode. Top screen in clamped to
 | ||||||
|     // the top of the frame, and the bottom screen is enlarged to match the top screen.
 |     // the top of the frame, and the bottom screen is enlarged to match the top screen.
 | ||||||
|     MobilePortrait, |     MobilePortrait, | ||||||
|  |  | ||||||
|  | @ -200,6 +200,11 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height, | ||||||
|                                          Settings::values.upright_screen.GetValue(), |                                          Settings::values.upright_screen.GetValue(), | ||||||
|                                          Settings::values.large_screen_proportion.GetValue()); |                                          Settings::values.large_screen_proportion.GetValue()); | ||||||
|             break; |             break; | ||||||
|  |         case Settings::LayoutOption::HybridScreen: | ||||||
|  |             layout = | ||||||
|  |                 Layout::HybridScreenLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||||
|  |                                            Settings::values.upright_screen.GetValue()); | ||||||
|  |             break; | ||||||
|         case Settings::LayoutOption::SideScreen: |         case Settings::LayoutOption::SideScreen: | ||||||
|             layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen.GetValue(), |             layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen.GetValue(), | ||||||
|                                              Settings::values.upright_screen.GetValue()); |                                              Settings::values.upright_screen.GetValue()); | ||||||
|  |  | ||||||
|  | @ -299,6 +299,80 @@ FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool swapped, bool upr | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | FramebufferLayout HybridScreenLayout(u32 width, u32 height, bool swapped, bool upright) { | ||||||
|  |     ASSERT(width > 0); | ||||||
|  |     ASSERT(height > 0); | ||||||
|  | 
 | ||||||
|  |     FramebufferLayout res{width, height, true, true, {}, {}, !upright, true, {}}; | ||||||
|  | 
 | ||||||
|  |     // Split the window into two parts. Give 2.25x width to the main screen,
 | ||||||
|  |     // and make a bar on the right side with 1x width top screen and 1.25x width bottom screen
 | ||||||
|  |     // To do that, find the total emulation box and maximize that based on window size
 | ||||||
|  |     const float window_aspect_ratio = static_cast<float>(height) / width; | ||||||
|  |     const float scale_factor = 2.25f; | ||||||
|  | 
 | ||||||
|  |     float main_screen_aspect_ratio = TOP_SCREEN_ASPECT_RATIO; | ||||||
|  |     float hybrid_area_aspect_ratio = 27.f / 65; | ||||||
|  |     float top_screen_aspect_ratio = TOP_SCREEN_ASPECT_RATIO; | ||||||
|  |     float bot_screen_aspect_ratio = BOT_SCREEN_ASPECT_RATIO; | ||||||
|  | 
 | ||||||
|  |     if (swapped) { | ||||||
|  |         main_screen_aspect_ratio = BOT_SCREEN_ASPECT_RATIO; | ||||||
|  |         hybrid_area_aspect_ratio = | ||||||
|  |             Core::kScreenBottomHeight * scale_factor / | ||||||
|  |             (Core::kScreenBottomWidth * scale_factor + Core::kScreenTopWidth); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (upright) { | ||||||
|  |         hybrid_area_aspect_ratio = 1.f / hybrid_area_aspect_ratio; | ||||||
|  |         main_screen_aspect_ratio = 1.f / main_screen_aspect_ratio; | ||||||
|  |         top_screen_aspect_ratio = TOP_SCREEN_UPRIGHT_ASPECT_RATIO; | ||||||
|  |         bot_screen_aspect_ratio = BOT_SCREEN_UPRIGHT_ASPECT_RATIO; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Common::Rectangle<u32> screen_window_area{0, 0, width, height}; | ||||||
|  |     Common::Rectangle<u32> total_rect = maxRectangle(screen_window_area, hybrid_area_aspect_ratio); | ||||||
|  |     Common::Rectangle<u32> large_main_screen = maxRectangle(total_rect, main_screen_aspect_ratio); | ||||||
|  |     Common::Rectangle<u32> side_rect = total_rect.Scale(1.f / scale_factor); | ||||||
|  |     Common::Rectangle<u32> small_top_screen = maxRectangle(side_rect, top_screen_aspect_ratio); | ||||||
|  |     Common::Rectangle<u32> small_bottom_screen = maxRectangle(side_rect, bot_screen_aspect_ratio); | ||||||
|  | 
 | ||||||
|  |     if (window_aspect_ratio < hybrid_area_aspect_ratio) { | ||||||
|  |         large_main_screen = large_main_screen.TranslateX((width - total_rect.GetWidth()) / 2); | ||||||
|  |     } else { | ||||||
|  |         large_main_screen = large_main_screen.TranslateY((height - total_rect.GetHeight()) / 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Scale the bottom screen so it's width is the same as top screen
 | ||||||
|  |     small_bottom_screen = small_bottom_screen.Scale(1.25f); | ||||||
|  |     if (upright) { | ||||||
|  |         large_main_screen = large_main_screen.TranslateY(small_bottom_screen.GetHeight()); | ||||||
|  |         // Shift small bottom screen to upper right corner
 | ||||||
|  |         small_bottom_screen = | ||||||
|  |             small_bottom_screen.TranslateX(large_main_screen.right - small_bottom_screen.GetWidth()) | ||||||
|  |                 .TranslateY(large_main_screen.top - small_bottom_screen.GetHeight()); | ||||||
|  | 
 | ||||||
|  |         // Shift small top screen to upper left corner
 | ||||||
|  |         small_top_screen = small_top_screen.TranslateX(large_main_screen.left) | ||||||
|  |                                .TranslateY(large_main_screen.top - small_bottom_screen.GetHeight()); | ||||||
|  |     } else { | ||||||
|  |         // Shift the small bottom screen to the bottom right corner
 | ||||||
|  |         small_bottom_screen = | ||||||
|  |             small_bottom_screen.TranslateX(large_main_screen.right) | ||||||
|  |                 .TranslateY(large_main_screen.GetHeight() + large_main_screen.top - | ||||||
|  |                             small_bottom_screen.GetHeight()); | ||||||
|  | 
 | ||||||
|  |         // Shift small top screen to upper right corner
 | ||||||
|  |         small_top_screen = | ||||||
|  |             small_top_screen.TranslateX(large_main_screen.right).TranslateY(large_main_screen.top); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     res.top_screen = small_top_screen; | ||||||
|  |     res.additional_screen = swapped ? small_bottom_screen : large_main_screen; | ||||||
|  |     res.bottom_screen = swapped ? large_main_screen : small_bottom_screen; | ||||||
|  |     return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| FramebufferLayout SideFrameLayout(u32 width, u32 height, bool swapped, bool upright) { | FramebufferLayout SideFrameLayout(u32 width, u32 height, bool swapped, bool upright) { | ||||||
|     ASSERT(width > 0); |     ASSERT(width > 0); | ||||||
|     ASSERT(height > 0); |     ASSERT(height > 0); | ||||||
|  |  | ||||||
|  | @ -37,6 +37,9 @@ struct FramebufferLayout { | ||||||
|     Common::Rectangle<u32> bottom_screen; |     Common::Rectangle<u32> bottom_screen; | ||||||
|     bool is_rotated = true; |     bool is_rotated = true; | ||||||
| 
 | 
 | ||||||
|  |     bool additional_screen_enabled; | ||||||
|  |     Common::Rectangle<u32> additional_screen; | ||||||
|  | 
 | ||||||
|     CardboardSettings cardboard; |     CardboardSettings cardboard; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -99,6 +102,15 @@ FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool is_swapped, bool | ||||||
|  */ |  */ | ||||||
| FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool is_swapped, bool upright, | FramebufferLayout LargeFrameLayout(u32 width, u32 height, bool is_swapped, bool upright, | ||||||
|                                    float scale_factor); |                                    float scale_factor); | ||||||
|  | /**
 | ||||||
|  |  * Factory method for constructing a frame with 2.5 times bigger top screen on the right, | ||||||
|  |  * and 1x top and bottom screen on the left | ||||||
|  |  * @param width Window framebuffer width in pixels | ||||||
|  |  * @param height Window framebuffer height in pixels | ||||||
|  |  * @param is_swapped if true, the bottom screen will be the large display | ||||||
|  |  * @return Newly created FramebufferLayout object with default screen regions initialized | ||||||
|  |  */ | ||||||
|  | FramebufferLayout HybridScreenLayout(u32 width, u32 height, bool swapped, bool upright); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Factory method for constructing a Frame with the Top screen and bottom |  * Factory method for constructing a Frame with the Top screen and bottom | ||||||
|  |  | ||||||
|  | @ -942,6 +942,15 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|         ApplySecondLayerOpacity(); |         ApplySecondLayerOpacity(); | ||||||
|         DrawTopScreen(layout, top_screen); |         DrawTopScreen(layout, top_screen); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     if (layout.additional_screen_enabled) { | ||||||
|  |         const auto& additional_screen = layout.additional_screen; | ||||||
|  |         if (!Settings::values.swap_screen.GetValue()) { | ||||||
|  |             DrawTopScreen(layout, additional_screen); | ||||||
|  |         } else { | ||||||
|  |             DrawBottomScreen(layout, additional_screen); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     ResetSecondLayerOpacity(); |     ResetSecondLayerOpacity(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue