From 065fecff6e21718bb3ded428e8d9fa6c53dba5f3 Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Sun, 2 Mar 2025 17:22:57 +0100 Subject: [PATCH] Add mode to force 50:50 ratio in fullscreen mode --- include/Menus/ScalingRatioMenu.hpp | 1 + include/display_structs.hpp | 1 + include/frontend.hpp | 6 ++ source/Menus/ScalingRatioMenu.cpp | 9 +++ source/WindowScreen.cpp | 101 ++++++++++++++++++++++++----- source/WindowScreen_Menu.cpp | 9 +++ source/frontend.cpp | 30 +++++++++ 7 files changed, 140 insertions(+), 17 deletions(-) diff --git a/include/Menus/ScalingRatioMenu.hpp b/include/Menus/ScalingRatioMenu.hpp index ce1ee41..dcc7303 100755 --- a/include/Menus/ScalingRatioMenu.hpp +++ b/include/Menus/ScalingRatioMenu.hpp @@ -17,6 +17,7 @@ enum ScalingRatioMenuOutAction{ SCALING_RATIO_MENU_NON_INT_SCALING_BOTTOM, SCALING_RATIO_MENU_ALGO_INC, SCALING_RATIO_MENU_ALGO_DEC, + SCALING_RATIO_MENU_FORCE_SAME_SCALING, }; class ScalingRatioMenu : public OptionSelectionMenu { diff --git a/include/display_structs.hpp b/include/display_structs.hpp index cb85182..2a68c8e 100755 --- a/include/display_structs.hpp +++ b/include/display_structs.hpp @@ -44,6 +44,7 @@ struct ScreenInfo { bool v_sync_enabled; bool async; int top_scaling, bot_scaling; + bool force_same_scaling; float non_integer_top_scaling, non_integer_bot_scaling; bool bfi; int bfi_divider; diff --git a/include/frontend.hpp b/include/frontend.hpp index 09acd72..86b3ca2 100755 --- a/include/frontend.hpp +++ b/include/frontend.hpp @@ -241,6 +241,7 @@ private: void menu_scaling_change(bool positive); void window_scaling_change(bool positive); void rotation_change(int &value, bool right); + void force_same_scaling_change(); void ratio_change(bool top_priority, bool cycle = false); void bfi_change(); void input_toggle_change(bool &target); @@ -271,6 +272,7 @@ private: void set_position_screens(sf::Vector2f &curr_top_screen_size, sf::Vector2f &curr_bot_screen_size, int offset_x, int offset_y, int max_x, int max_y, bool do_work = true); float get_max_float_screen_multiplier(ResizingScreenData *own_screen, int width_limit, int height_limit, int other_rotation); int prepare_screen_ratio(ResizingScreenData *own_screen, int width_limit, int height_limit, int other_rotation); + float get_ratio_compared_other_screen(ResizingScreenData *own_screen, ResizingScreenData* other_screen, float other_scaling); bool can_non_integerly_scale(); void calc_scaling_resize_screens(ResizingScreenData *own_screen, ResizingScreenData* other_screen, bool increase, bool mantain, bool set_to_zero, bool cycle); void rescale_nonint_subscreen(ResizingScreenData *main_screen_resize_data, ResizingScreenData *sub_screen_resize_data); @@ -278,6 +280,8 @@ private: void non_int_scale_screens_with_main(ResizingScreenData *main_screen_resize_data, ResizingScreenData *sub_screen_resize_data, int sub_min_width, int sub_height_min); void non_int_scale_screens_both(ResizingScreenData *main_screen_resize_data, ResizingScreenData *sub_screen_resize_data, int free_width, int free_height, float multiplier_main, int main_min_width, int main_height_min, int sub_min_width, int sub_height_min); void non_integer_scale_screens(ResizingScreenData *top_screen_resize_data, ResizingScreenData *bot_screen_resize_data); + void merge_screens_data(ResizingScreenData* top_screen_resize_data, ResizingScreenData* bot_screen_resize_data, ResizingScreenData* merged_screen_resize_data, BottomRelativePosition bottom_pos); + bool prepare_screens_same_scaling_factor(ResizingScreenData* top_screen_resize_data, ResizingScreenData* bot_screen_resize_data); void prepare_size_ratios(bool top_increase, bool bot_increase, bool cycle = false); int get_fullscreen_offset_x(int top_width, int top_height, int bot_width, int bot_height); int get_fullscreen_offset_y(int top_width, int top_height, int bot_width, int bot_height); @@ -342,7 +346,9 @@ void override_set_data_to_screen_info(override_win_data &override_win, ScreenInf void reset_screen_info(ScreenInfo &info); bool load_screen_info(std::string key, std::string value, std::string base, ScreenInfo &info); std::string save_screen_info(std::string base, const ScreenInfo &info); +const PARData* get_base_par(); void get_par_size(int &width, int &height, float multiplier_factor, const PARData *correction_factor); +void get_par_size(float &width, float &height, float multiplier_factor, const PARData *correction_factor); float get_par_mult_factor(float width, float height, float max_width, float max_height, const PARData *correction_factor, bool is_rotated); void update_output(FrontendData* frontend_data, double frame_time = 0.0, VideoOutputData *out_buf = NULL); void update_connected_3ds_ds(FrontendData* frontend_data, const CaptureDevice &old_cc_device, const CaptureDevice &new_cc_device); diff --git a/source/Menus/ScalingRatioMenu.cpp b/source/Menus/ScalingRatioMenu.cpp index aad1374..dd380de 100755 --- a/source/Menus/ScalingRatioMenu.cpp +++ b/source/Menus/ScalingRatioMenu.cpp @@ -33,11 +33,17 @@ static const ScalingRatioMenuOptionInfo ratio_algo_option = { .is_inc = true, .dec_str = "<", .inc_str = ">", .inc_out_action = SCALING_RATIO_MENU_ALGO_INC, .out_action = SCALING_RATIO_MENU_ALGO_DEC}; +static const ScalingRatioMenuOptionInfo force_same_scaling_option = { +.base_name = "Allow Different Scaling", .false_name = "Force 50/50 Ratio", +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = SCALING_RATIO_MENU_NO_ACTION, +.out_action = SCALING_RATIO_MENU_FORCE_SAME_SCALING}; + static const ScalingRatioMenuOptionInfo* pollable_options[] = { &ratio_option, &top_fill_option, &bot_fill_option, &ratio_algo_option, +&force_same_scaling_option, }; ScalingRatioMenu::ScalingRatioMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){ @@ -144,6 +150,9 @@ void ScalingRatioMenu::prepare(float menu_scaling_factor, int view_size_x, int v case SCALING_RATIO_MENU_ALGO_DEC: this->labels[index]->setText(this->setTextOptionString(real_index, get_name_non_int_mode(info->non_integer_mode))); break; + case SCALING_RATIO_MENU_FORCE_SAME_SCALING: + this->labels[index]->setText(this->setTextOptionBool(real_index, info->force_same_scaling)); + break; default: break; } diff --git a/source/WindowScreen.cpp b/source/WindowScreen.cpp index c1c3034..d88dd65 100755 --- a/source/WindowScreen.cpp +++ b/source/WindowScreen.cpp @@ -754,8 +754,12 @@ void WindowScreen::set_position_screens(sf::Vector2f &curr_top_screen_size, sf:: this->m_height = bot_end_y; } +static bool is_size_valid(sf::Vector2f &size) { + return (size.x > 0.0) && (size.y > 0.0); +} + float WindowScreen::get_max_float_screen_multiplier(ResizingScreenData *own_screen, int width_limit, int height_limit, int other_rotation) { - if((own_screen->size.x < 1.0) || (own_screen->size.y < 1.0)) + if(!is_size_valid(own_screen->size)) return 0; if((other_rotation / 10) % 2) @@ -784,11 +788,15 @@ int WindowScreen::prepare_screen_ratio(ResizingScreenData *own_screen, int width return this->get_max_float_screen_multiplier(own_screen, width_limit, height_limit, other_rotation); } -void WindowScreen::calc_scaling_resize_screens(ResizingScreenData *own_screen, ResizingScreenData* other_screen, bool increase, bool mantain, bool set_to_zero, bool cycle) { +float WindowScreen::get_ratio_compared_other_screen(ResizingScreenData *own_screen, ResizingScreenData* other_screen, float other_scaling) { int other_width = other_screen->size.x; int other_height = other_screen->size.y; - get_par_size(other_width, other_height, 1, other_screen->par); - int chosen_ratio = prepare_screen_ratio(own_screen, other_width, other_height, other_screen->rotation); + get_par_size(other_width, other_height, other_scaling, other_screen->par); + return prepare_screen_ratio(own_screen, other_width, other_height, other_screen->rotation); +} + +void WindowScreen::calc_scaling_resize_screens(ResizingScreenData *own_screen, ResizingScreenData* other_screen, bool increase, bool mantain, bool set_to_zero, bool cycle) { + int chosen_ratio = get_ratio_compared_other_screen(own_screen, other_screen, 1); if(chosen_ratio <= 0) { chosen_ratio = prepare_screen_ratio(own_screen, 0, 0, other_screen->rotation); if(chosen_ratio <= 0) @@ -805,23 +813,17 @@ void WindowScreen::calc_scaling_resize_screens(ResizingScreenData *own_screen, R (*own_screen->scaling) = chosen_ratio; if(set_to_zero) (*own_screen->scaling) = 0; - int own_height = own_screen->size.y; - int own_width = own_screen->size.x; - get_par_size(own_width, own_height, *own_screen->scaling, own_screen->par); if((increase && ((old_scaling == (*own_screen->scaling)) || ((*other_screen->scaling) == 0)) || (mantain && ((*other_screen->scaling) == 0))) && ((*own_screen->scaling) > 0)) (*other_screen->scaling) = 0; else - (*other_screen->scaling) = prepare_screen_ratio(other_screen, own_width, own_height, own_screen->rotation); + (*other_screen->scaling) = get_ratio_compared_other_screen(other_screen, own_screen, *own_screen->scaling); if((*other_screen->scaling) < 0) (*other_screen->scaling) = 0; if((this->m_stype == ScreenType::JOINT) && (((*own_screen->scaling) > 0) || (((*other_screen->scaling) == 0) && ((*own_screen->scaling) == 0)))) { // Due to size differences, it may be possible that // the chosen screen might be able to increase its // scaling even more without compromising the other one... - other_width = other_screen->size.x; - other_height = other_screen->size.y; - get_par_size(other_width, other_height, *other_screen->scaling, other_screen->par); - (*own_screen->scaling) = prepare_screen_ratio(own_screen, other_width, other_height, other_screen->rotation); + (*own_screen->scaling) = get_ratio_compared_other_screen(own_screen, other_screen, *other_screen->scaling); if((*own_screen->scaling) < 0) (*own_screen->scaling) = 0; } @@ -945,6 +947,64 @@ void WindowScreen::non_integer_scale_screens(ResizingScreenData *top_screen_resi } } +void WindowScreen::merge_screens_data(ResizingScreenData* top_screen_resize_data, ResizingScreenData* bot_screen_resize_data, ResizingScreenData* merged_screen_resize_data, BottomRelativePosition bottom_pos) { + // Due to PARs and rotations, this is a bit annoying, but whatever... + float top_width = top_screen_resize_data->size.x; + float top_height = top_screen_resize_data->size.y; + get_par_size(top_width, top_height, 1.0, top_screen_resize_data->par); + float bot_width = bot_screen_resize_data->size.x; + float bot_height = bot_screen_resize_data->size.y; + get_par_size(bot_width, bot_height, 1.0, bot_screen_resize_data->par); + if((top_screen_resize_data->rotation / 10) % 2) + std::swap(top_width, top_height); + if((bot_screen_resize_data->rotation / 10) % 2) + std::swap(bot_width, bot_height); + float final_width = std::max(top_width, bot_width); + float final_height = std::max(top_height, bot_height); + switch(bottom_pos) { + case UNDER_TOP: + case ABOVE_TOP: + final_height = top_height + bot_height; + break; + case LEFT_TOP: + case RIGHT_TOP: + final_width = top_width + bot_width; + break; + default: + break; + } + merged_screen_resize_data->size.x = final_width; + merged_screen_resize_data->size.y = final_height; + if(top_screen_resize_data->use_non_int_scaling || bot_screen_resize_data->use_non_int_scaling) + merged_screen_resize_data->use_non_int_scaling = true; + else + merged_screen_resize_data->use_non_int_scaling = false; + merged_screen_resize_data->rotation = 0; + *merged_screen_resize_data->scaling = 1.0; + *merged_screen_resize_data->non_int_scaling = 1.0; + merged_screen_resize_data->par = get_base_par(); +} + +bool WindowScreen::prepare_screens_same_scaling_factor(ResizingScreenData* top_screen_resize_data, ResizingScreenData* bot_screen_resize_data) { + if((!is_size_valid(top_screen_resize_data->size)) || (!is_size_valid(bot_screen_resize_data->size))) + return false; + int scaling_merged = 1; + float non_int_scaling_merged = 1.0; + ResizingScreenData merged_screen_resize_data = {.size = {}, .scaling = &scaling_merged, .non_int_scaling = &non_int_scaling_merged, .use_non_int_scaling = false, .rotation = 0, .par = NULL}; + merge_screens_data(top_screen_resize_data, bot_screen_resize_data, &merged_screen_resize_data, this->m_info.bottom_pos); + non_int_scaling_merged = this->get_max_float_screen_multiplier(&merged_screen_resize_data, 0, 0, 0); + scaling_merged = non_int_scaling_merged; + if(non_int_scaling_merged < 1.0) + return false; + *top_screen_resize_data->non_int_scaling = scaling_merged; + *bot_screen_resize_data->non_int_scaling = scaling_merged; + if(merged_screen_resize_data.use_non_int_scaling) { + *top_screen_resize_data->non_int_scaling = non_int_scaling_merged; + *bot_screen_resize_data->non_int_scaling = non_int_scaling_merged; + } + return true; +} + void WindowScreen::prepare_size_ratios(bool top_increase, bool bot_increase, bool cycle) { if(!this->m_info.is_fullscreen) return; @@ -972,12 +1032,19 @@ void WindowScreen::prepare_size_ratios(bool top_increase, bool bot_increase, boo this->m_info.bot_par = 0; ResizingScreenData top_screen_resize_data = {.size = top_screen_size, .scaling = &this->m_info.top_scaling, .non_int_scaling = &this->m_info.non_integer_top_scaling, .use_non_int_scaling = this->m_info.use_non_integer_scaling_top, .rotation = this->m_info.top_rotation, .par = this->possible_pars[this->m_info.top_par]}; ResizingScreenData bot_screen_resize_data = {.size = bot_screen_size, .scaling = &this->m_info.bot_scaling, .non_int_scaling = &this->m_info.non_integer_bot_scaling, .use_non_int_scaling = this->m_info.use_non_integer_scaling_bottom, .rotation = this->m_info.bot_rotation, .par = this->possible_pars[this->m_info.bot_par]}; - if(prioritize_top) - calc_scaling_resize_screens(&top_screen_resize_data, &bot_screen_resize_data, top_increase, try_mantain_ratio, this->m_stype == ScreenType::BOTTOM, cycle); - else - calc_scaling_resize_screens(&bot_screen_resize_data, &top_screen_resize_data, bot_increase, try_mantain_ratio, this->m_stype == ScreenType::TOP, cycle); - this->non_integer_scale_screens(&top_screen_resize_data, &bot_screen_resize_data); + bool processed = false; + if(this->m_stype == ScreenType::JOINT && this->m_info.force_same_scaling) + processed = this->prepare_screens_same_scaling_factor(&top_screen_resize_data, &bot_screen_resize_data); + + if(!processed) { + if(prioritize_top) + calc_scaling_resize_screens(&top_screen_resize_data, &bot_screen_resize_data, top_increase, try_mantain_ratio, this->m_stype == ScreenType::BOTTOM, cycle); + else + calc_scaling_resize_screens(&bot_screen_resize_data, &top_screen_resize_data, bot_increase, try_mantain_ratio, this->m_stype == ScreenType::TOP, cycle); + + this->non_integer_scale_screens(&top_screen_resize_data, &bot_screen_resize_data); + } } int WindowScreen::get_fullscreen_offset_x(int top_width, int top_height, int bot_width, int bot_height) { diff --git a/source/WindowScreen_Menu.cpp b/source/WindowScreen_Menu.cpp index 9e7ebf0..98ae8e1 100755 --- a/source/WindowScreen_Menu.cpp +++ b/source/WindowScreen_Menu.cpp @@ -376,6 +376,12 @@ void WindowScreen::rotation_change(int &value, bool right) { this->future_operations.call_rotate = true; } +void WindowScreen::force_same_scaling_change() { + this->m_info.force_same_scaling = !this->m_info.force_same_scaling; + this->prepare_size_ratios(true, true, false); + this->future_operations.call_screen_settings_update = true; +} + void WindowScreen::ratio_change(bool top_priority, bool cycle) { this->prepare_size_ratios(top_priority, !top_priority, cycle); this->future_operations.call_screen_settings_update = true; @@ -1926,6 +1932,9 @@ void WindowScreen::poll(bool do_everything) { case SCALING_RATIO_MENU_ALGO_INC: this->non_int_mode_change(true); break; + case SCALING_RATIO_MENU_FORCE_SAME_SCALING: + this->force_same_scaling_change(); + break; default: break; } diff --git a/source/frontend.cpp b/source/frontend.cpp index a6243c3..34a4329 100755 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -441,6 +441,7 @@ void reset_screen_info(ScreenInfo &info) { info.async = true; info.top_scaling = DEFAULT_NO_SCALING_VALUE; info.bot_scaling = DEFAULT_NO_SCALING_VALUE; + info.force_same_scaling = false; info.non_integer_top_scaling = DEFAULT_NO_SCALING_VALUE; info.non_integer_bot_scaling = DEFAULT_NO_SCALING_VALUE; info.bfi = false; @@ -607,6 +608,10 @@ bool load_screen_info(std::string key, std::string value, std::string base, Scre info.rounded_corners_fix = std::stoi(value); return true; } + if(key == (base + "force_same_scaling")) { + info.force_same_scaling = std::stoi(value); + return true; + } if(key == (base + "top_par")) { info.top_par = std::stoi(value); return true; @@ -707,6 +712,7 @@ std::string save_screen_info(std::string base, const ScreenInfo &info) { out += base + "frame_blending_top=" + std::to_string(info.frame_blending_top) + "\n"; out += base + "frame_blending_bot=" + std::to_string(info.frame_blending_bot) + "\n"; out += base + "window_enabled=" + std::to_string(info.window_enabled) + "\n"; + out += base + "force_same_scaling=" + std::to_string(info.force_same_scaling) + "\n"; return out; } @@ -722,6 +728,10 @@ void joystick_axis_poll(std::queue &events_queue) { } } +const PARData* get_base_par() { + return basic_possible_pars[0]; +} + void get_par_size(int &width, int &height, float multiplier_factor, const PARData *correction_factor) { width *= multiplier_factor; height *= multiplier_factor; @@ -743,6 +753,26 @@ void get_par_size(int &width, int &height, float multiplier_factor, const PARDat } } +void get_par_size(float &width, float &height, float multiplier_factor, const PARData *correction_factor) { + width *= multiplier_factor; + height *= multiplier_factor; + float correction_factor_divisor = correction_factor->width_multiplier; + if(correction_factor->is_width_main) + correction_factor_divisor = correction_factor->width_divisor; + if(correction_factor->is_fit) { + if(correction_factor->is_width_main) + width = (height * correction_factor->width_multiplier) / correction_factor_divisor; + else + height = (width * correction_factor->width_divisor) / correction_factor_divisor; + } + else { + if(correction_factor->is_width_main) + width = (width * correction_factor->width_multiplier) / correction_factor_divisor; + else + height = (height * correction_factor->width_divisor) / correction_factor_divisor; + } +} + float get_par_mult_factor(float width, float height, float max_width, float max_height, const PARData *correction_factor, bool is_rotated) { float correction_factor_divisor = correction_factor->width_multiplier; float correction_factor_multiplier = correction_factor->width_divisor;