diff --git a/CMakeLists.txt b/CMakeLists.txt index d35d0c5..231f204 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -490,7 +490,7 @@ if(MSVC) else() set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "$<$:-O3>") endif() -add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/Menus/VideoEffectsMenu.cpp source/CaptureDataBuffers.cpp source/Menus/InputMenu.cpp source/Menus/AudioDeviceMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES}) +add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/Menus/VideoEffectsMenu.cpp source/CaptureDataBuffers.cpp source/Menus/InputMenu.cpp source/Menus/AudioDeviceMenu.cpp source/Menus/SeparatorMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES}) if(NOT ("${EXTRA_DEPENDENCIES}" STREQUAL "")) diff --git a/ftdi_lib_files/notice.md b/ftdi_lib_files/notice.md index e62e9fb..8365857 100644 --- a/ftdi_lib_files/notice.md +++ b/ftdi_lib_files/notice.md @@ -10,8 +10,8 @@ source to prevent build errors. Certain files which are not needed were removed from the libraries' archives to save on space. -Feel free to contact me if you would like me to have the files removed, -if an agreement about their availability is reached. +Feel free to contact me if you would like the files to be removed, +if an agreement about their availability can be reached. Changing FTDI\_BASE\_URL to https://ftdichip.com/wp-content/uploads will switch to automatic download during builds. diff --git a/include/Menus/SeparatorMenu.hpp b/include/Menus/SeparatorMenu.hpp new file mode 100644 index 0000000..4affa1e --- /dev/null +++ b/include/Menus/SeparatorMenu.hpp @@ -0,0 +1,43 @@ +#ifndef __SEPARATORMENU_HPP +#define __SEPARATORMENU_HPP + +#include "OptionSelectionMenu.hpp" +#include + +#include "TextRectangle.hpp" +#include "sfml_gfx_structs.hpp" +#include "display_structs.hpp" + +enum SeparatorMenuOutAction{ + SEPARATOR_MENU_NO_ACTION, + SEPARATOR_MENU_BACK, + SEPARATOR_MENU_SIZE_DEC_1, + SEPARATOR_MENU_SIZE_INC_1, + SEPARATOR_MENU_SIZE_DEC_10, + SEPARATOR_MENU_SIZE_INC_10, + SEPARATOR_MENU_WINDOW_MUL_DEC, + SEPARATOR_MENU_WINDOW_MUL_INC, + SEPARATOR_MENU_FULLSCREEN_MUL_DEC, + SEPARATOR_MENU_FULLSCREEN_MUL_INC, +}; + +class SeparatorMenu : public OptionSelectionMenu { +public: + SeparatorMenu(bool font_load_success, sf::Font &text_font); + ~SeparatorMenu(); + void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info); + void insert_data(bool is_fullscreen); + SeparatorMenuOutAction selected_index = SeparatorMenuOutAction::SEPARATOR_MENU_NO_ACTION; + void reset_output_option(); +protected: + bool is_option_inc_dec(int index); + void set_output_option(int index, int action); + int get_num_options(); + std::string get_string_option(int index, int action); + void class_setup(); +private: + int *options_indexes; + int num_enabled_options; + std::string get_name_multiplier(int index, float value, bool is_fullscreen); +}; +#endif diff --git a/include/Menus/VideoMenu.hpp b/include/Menus/VideoMenu.hpp index af5feb7..a5d9042 100755 --- a/include/Menus/VideoMenu.hpp +++ b/include/Menus/VideoMenu.hpp @@ -40,6 +40,7 @@ enum VideoMenuOutAction{ VIDEO_MENU_SCALING_RATIO_SETTINGS, VIDEO_MENU_CHANGE_TITLEBAR, VIDEO_MENU_VIDEO_EFFECTS_SETTINGS, + VIDEO_MENU_SEPARATOR_SETTINGS, }; class VideoMenu : public OptionSelectionMenu { diff --git a/include/display_structs.hpp b/include/display_structs.hpp index 2a68c8e..ea6d933 100755 --- a/include/display_structs.hpp +++ b/include/display_structs.hpp @@ -16,10 +16,16 @@ #define MAX_WINDOW_SCALING_VALUE 45.0 #define WINDOW_SCALING_CHANGE 0.5 +#define SEP_FOLLOW_SCALING_MULTIPLIER WINDOW_SCALING_CHANGE +#define SEP_WINDOW_SCALING_MIN_MULTIPLIER SEP_FOLLOW_SCALING_MULTIPLIER +#define SEP_FULLSCREEN_SCALING_MIN_MULTIPLIER DEFAULT_WINDOW_SCALING_VALUE +#define DEFAULT_SEP_SIZE 0 +#define MAX_SEP_SIZE 1000 + enum ScreenType { TOP, BOTTOM, JOINT }; enum BottomRelativePosition { UNDER_TOP, LEFT_TOP, ABOVE_TOP, RIGHT_TOP, BOT_REL_POS_END }; enum NonIntegerScalingModes { SMALLER_PRIORITY, INVERSE_PROPORTIONAL_PRIORITY, EQUAL_PRIORITY, PROPORTIONAL_PRIORITY, BIGGER_PRIORITY, END_NONINT_SCALE_MODES }; -enum CurrMenuType { DEFAULT_MENU_TYPE, CONNECT_MENU_TYPE, MAIN_MENU_TYPE, VIDEO_MENU_TYPE, AUDIO_MENU_TYPE, CROP_MENU_TYPE, TOP_PAR_MENU_TYPE, BOTTOM_PAR_MENU_TYPE, ROTATION_MENU_TYPE, OFFSET_MENU_TYPE, BFI_MENU_TYPE, LOAD_MENU_TYPE, SAVE_MENU_TYPE, RESOLUTION_MENU_TYPE, EXTRA_MENU_TYPE, STATUS_MENU_TYPE, LICENSES_MENU_TYPE, RELATIVE_POS_MENU_TYPE, SHORTCUTS_MENU_TYPE, ACTION_SELECTION_MENU_TYPE, SCALING_RATIO_MENU_TYPE, ISN_MENU_TYPE, VIDEO_EFFECTS_MENU_TYPE, INPUT_MENU_TYPE, AUDIO_DEVICE_MENU_TYPE }; +enum CurrMenuType { DEFAULT_MENU_TYPE, CONNECT_MENU_TYPE, MAIN_MENU_TYPE, VIDEO_MENU_TYPE, AUDIO_MENU_TYPE, CROP_MENU_TYPE, TOP_PAR_MENU_TYPE, BOTTOM_PAR_MENU_TYPE, ROTATION_MENU_TYPE, OFFSET_MENU_TYPE, BFI_MENU_TYPE, LOAD_MENU_TYPE, SAVE_MENU_TYPE, RESOLUTION_MENU_TYPE, EXTRA_MENU_TYPE, STATUS_MENU_TYPE, LICENSES_MENU_TYPE, RELATIVE_POS_MENU_TYPE, SHORTCUTS_MENU_TYPE, ACTION_SELECTION_MENU_TYPE, SCALING_RATIO_MENU_TYPE, ISN_MENU_TYPE, VIDEO_EFFECTS_MENU_TYPE, INPUT_MENU_TYPE, AUDIO_DEVICE_MENU_TYPE, SEPARATOR_MENU_TYPE }; enum InputColorspaceMode { FULL_COLORSPACE, DS_COLORSPACE, GBA_COLORSPACE, INPUT_COLORSPACE_END }; enum FrameBlendingMode { NO_FRAME_BLENDING, FULL_FRAME_BLENDING, DS_3D_BOTH_SCREENS_FRAME_BLENDING, FRAME_BLENDING_END }; @@ -44,6 +50,9 @@ struct ScreenInfo { bool v_sync_enabled; bool async; int top_scaling, bot_scaling; + int separator_pixel_size; + float separator_windowed_multiplier; + float separator_fullscreen_multiplier; bool force_same_scaling; float non_integer_top_scaling, non_integer_bot_scaling; bool bfi; diff --git a/include/frontend.hpp b/include/frontend.hpp index 86b3ca2..934abf3 100755 --- a/include/frontend.hpp +++ b/include/frontend.hpp @@ -34,6 +34,7 @@ #include "VideoEffectsMenu.hpp" #include "InputMenu.hpp" #include "AudioDeviceMenu.hpp" +#include "SeparatorMenu.hpp" #include "display_structs.hpp" #include "event_structs.hpp" #include "shaders_list.hpp" @@ -155,6 +156,7 @@ private: VideoEffectsMenu *video_effects_menu; InputMenu *input_menu; AudioDeviceMenu *audio_device_menu; + SeparatorMenu *separator_menu; std::vector possible_crops; std::vector possible_crops_ds; std::vector possible_crops_with_games; @@ -251,6 +253,10 @@ private: void titlebar_change(); void input_colorspace_mode_change(bool positive); void frame_blending_mode_change(bool positive); + void separator_size_change(int change); + void separator_multiplier_change(bool positive, float& multiplier_to_check, float lower_limit, float upper_limit); + void separator_windowed_multiplier_change(bool positive); + void separator_fullscreen_multiplier_change(bool positive); bool query_reset_request(); void reset_held_times(bool force = true); void poll_window(bool do_everything); @@ -269,8 +275,8 @@ private: void window_bg_processing(); void display_data_to_window(bool actually_draw, bool is_debug = false); void window_render_call(); - 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); + 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, int separator_size_x, int separator_size_y, bool do_work = true); + float get_max_float_screen_multiplier(ResizingScreenData *own_screen, int width_limit, int height_limit, int other_rotation, bool is_two_screens_merged = false); 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(); @@ -283,8 +289,8 @@ private: 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); + int get_fullscreen_offset_x(int top_width, int top_height, int bot_width, int bot_height, int separator_contribute); + int get_fullscreen_offset_y(int top_width, int top_height, int bot_width, int bot_height, int separator_contribute); void resize_window_and_out_rects(bool do_work = true); void create_window(bool re_prepare_size, bool reset_text = true); std::string title_factory(); @@ -320,6 +326,7 @@ private: void setup_is_nitro_menu(bool reset_data = true); void setup_video_effects_menu(bool reset_data = true); void setup_input_menu(bool reset_data = true); + void setup_separator_menu(bool reset_data = true); void update_connection(); }; @@ -349,7 +356,6 @@ 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); void update_connected_specific_settings(FrontendData* frontend_data, const CaptureDevice &cc_device); diff --git a/source/Menus/SeparatorMenu.cpp b/source/Menus/SeparatorMenu.cpp new file mode 100644 index 0000000..a7b919f --- /dev/null +++ b/source/Menus/SeparatorMenu.cpp @@ -0,0 +1,148 @@ +#include "SeparatorMenu.hpp" + +#define NUM_TOTAL_MENU_OPTIONS (sizeof(pollable_options)/sizeof(pollable_options[0])) + +struct SeparatorMenuOptionInfo { + const std::string base_name; + const bool is_inc; + const std::string dec_str; + const std::string inc_str; + const SeparatorMenuOutAction inc_out_action; + const SeparatorMenuOutAction out_action; + const bool show_windowed; + const bool show_fullscreen; +}; + +static const SeparatorMenuOptionInfo separator_size_change_1_option = { +.base_name = "Separator Size:", +.is_inc = true, .dec_str = "-1", .inc_str = "+1", .inc_out_action = SEPARATOR_MENU_SIZE_INC_1, +.out_action = SEPARATOR_MENU_SIZE_DEC_1, +.show_windowed = true, .show_fullscreen = true}; + +static const SeparatorMenuOptionInfo separator_size_change_10_option = { +.base_name = "", +.is_inc = true, .dec_str = "-10", .inc_str = "+10", .inc_out_action = SEPARATOR_MENU_SIZE_INC_10, +.out_action = SEPARATOR_MENU_SIZE_DEC_10, +.show_windowed = true, .show_fullscreen = true}; + +static const SeparatorMenuOptionInfo separator_window_mul_change_option = { +.base_name = "Multiplier", +.is_inc = true, .dec_str = "<", .inc_str = ">", .inc_out_action = SEPARATOR_MENU_WINDOW_MUL_INC, +.out_action = SEPARATOR_MENU_WINDOW_MUL_DEC, +.show_windowed = true, .show_fullscreen = false}; + +static const SeparatorMenuOptionInfo separator_fullscreen_mul_change_option = { +.base_name = "Multiplier", +.is_inc = true, .dec_str = "<", .inc_str = ">", .inc_out_action = SEPARATOR_MENU_FULLSCREEN_MUL_INC, +.out_action = SEPARATOR_MENU_FULLSCREEN_MUL_DEC, +.show_windowed = false, .show_fullscreen = true}; + +static const SeparatorMenuOptionInfo* pollable_options[] = { +&separator_size_change_1_option, +&separator_size_change_10_option, +&separator_window_mul_change_option, +&separator_fullscreen_mul_change_option, +}; + +SeparatorMenu::SeparatorMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){ + this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS]; + this->initialize(font_load_success, text_font); + this->num_enabled_options = 0; +} + +SeparatorMenu::~SeparatorMenu() { + delete []this->options_indexes; +} + +void SeparatorMenu::class_setup() { + this->num_options_per_screen = 5; + this->min_elements_text_scaling_factor = num_options_per_screen + 2; + this->width_factor_menu = 16; + this->width_divisor_menu = 9; + this->base_height_factor_menu = 12; + this->base_height_divisor_menu = 6; + this->min_text_size = 0.3; + this->max_width_slack = 1.1; + this->menu_color = sf::Color(30, 30, 60, 192); + this->title = "Separator Settings"; + this->show_back_x = true; + this->show_x = false; + this->show_title = true; +} + +void SeparatorMenu::insert_data(bool is_fullscreen) { + this->num_enabled_options = 0; + for(int i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) { + if(is_fullscreen && (!pollable_options[i]->show_fullscreen)) + continue; + if((!is_fullscreen) && (!pollable_options[i]->show_windowed)) + continue; + this->options_indexes[this->num_enabled_options] = i; + this->num_enabled_options++; + } + this->prepare_options(); +} + +void SeparatorMenu::reset_output_option() { + this->selected_index = SeparatorMenuOutAction::SEPARATOR_MENU_NO_ACTION; +} + +void SeparatorMenu::set_output_option(int index, int action) { + if(index == BACK_X_OUTPUT_OPTION) + this->selected_index = SEPARATOR_MENU_BACK; + else if((action == INC_ACTION) && this->is_option_inc_dec(index)) + this->selected_index = pollable_options[this->options_indexes[index]]->inc_out_action; + else + this->selected_index = pollable_options[this->options_indexes[index]]->out_action; +} + +int SeparatorMenu::get_num_options() { + return this->num_enabled_options; +} + +std::string SeparatorMenu::get_string_option(int index, int action) { + if((action == INC_ACTION) && this->is_option_inc_dec(index)) + return pollable_options[this->options_indexes[index]]->inc_str; + if((action == DEC_ACTION) && this->is_option_inc_dec(index)) + return pollable_options[this->options_indexes[index]]->dec_str; + return pollable_options[this->options_indexes[index]]->base_name; +} + +bool SeparatorMenu::is_option_inc_dec(int index) { + return pollable_options[this->options_indexes[index]]->is_inc; +} + +std::string SeparatorMenu::get_name_multiplier(int index, float value, bool is_fullscreen) { + if((!is_fullscreen) && (value == SEP_FOLLOW_SCALING_MULTIPLIER)) + return this->get_string_option(index, DEFAULT_ACTION) + ": " + "Scaling"; + return this->setTextOptionFloat(index, value); +} + +void SeparatorMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info) { + int num_pages = this->get_num_pages(); + if(this->future_data.page >= num_pages) + this->future_data.page = num_pages - 1; + int start = this->future_data.page * this->num_options_per_screen; + for(int i = 0; i < this->num_options_per_screen + 1; i++) { + int index = (i * this->single_option_multiplier) + this->elements_start_id; + if(!this->future_enabled_labels[index]) + continue; + int real_index = start + i; + int option_index = this->options_indexes[real_index]; + switch(pollable_options[option_index]->out_action) { + case SEPARATOR_MENU_SIZE_DEC_10: + this->labels[index]->setText(std::to_string(info->separator_pixel_size)); + break; + case SEPARATOR_MENU_WINDOW_MUL_DEC: + this->labels[index]->setText(get_name_multiplier(real_index, info->separator_windowed_multiplier, info->is_fullscreen)); + break; + case SEPARATOR_MENU_FULLSCREEN_MUL_DEC: + this->labels[index]->setText(get_name_multiplier(real_index, info->separator_fullscreen_multiplier, info->is_fullscreen)); + break; + default: + break; + } + } + + this->base_prepare(menu_scaling_factor, view_size_x, view_size_y); +} diff --git a/source/Menus/VideoMenu.cpp b/source/Menus/VideoMenu.cpp index ed1638e..2c79718 100755 --- a/source/Menus/VideoMenu.cpp +++ b/source/Menus/VideoMenu.cpp @@ -188,6 +188,13 @@ static const VideoMenuOptionInfo video_effects_settings_option = { .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = VIDEO_MENU_NO_ACTION, .out_action = VIDEO_MENU_VIDEO_EFFECTS_SETTINGS}; +static const VideoMenuOptionInfo separator_settings_option = { +.base_name = "Separator Settings", .false_name = "", +.active_fullscreen = true, .active_windowed_screen = true, .requires_titlebar_possible = false, +.active_joint_screen = true, .active_top_screen = false, .active_bottom_screen = false, +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = VIDEO_MENU_NO_ACTION, +.out_action = VIDEO_MENU_SEPARATOR_SETTINGS}; + static const VideoMenuOptionInfo* pollable_options[] = { &crop_option, &window_scaling_option, @@ -195,6 +202,7 @@ static const VideoMenuOptionInfo* pollable_options[] = { &scaling_ratio_settings_option, &menu_scaling_option, &bottom_screen_pos_option, +&separator_settings_option, &vsync_option, &async_option, &blur_option, diff --git a/source/WindowScreen.cpp b/source/WindowScreen.cpp index d88dd65..c984c94 100755 --- a/source/WindowScreen.cpp +++ b/source/WindowScreen.cpp @@ -31,6 +31,10 @@ struct shader_and_data { static std::vector usable_shaders; +static bool is_size_valid(sf::Vector2f &size) { + return (size.x > 0.0) && (size.y > 0.0); +} + WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, SharedData* shared_data, AudioData* audio_data, ConsumerMutex *draw_lock, bool created_proper_folder) { this->draw_lock = draw_lock; this->m_stype = stype; @@ -673,7 +677,39 @@ void WindowScreen::window_render_call() { } } -void WindowScreen::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) { +static bool should_have_separator(sf::Vector2f top_screen_size, sf::Vector2f bot_screen_size, float top_scaling, float bot_scaling, ScreenType stype) { + if(stype != ScreenType::JOINT) + return false; + if((!is_size_valid(top_screen_size)) || (!is_size_valid(bot_screen_size))) + return false; + if((top_scaling <= 0) || (bot_scaling <= 0)) + return false; + return true; +} + +static int get_separator_size_xy(float top_scaling, float bot_scaling, int separator_size, float separator_multiplier, bool is_fullscreen) { + if((!is_fullscreen) && (separator_multiplier == SEP_FOLLOW_SCALING_MULTIPLIER)) + return separator_size * top_scaling; + return separator_size * separator_multiplier; +} + +static int get_separator_size_x(sf::Vector2f top_screen_size, sf::Vector2f bot_screen_size, float top_scaling, float bot_scaling, ScreenType stype, BottomRelativePosition bottom_pos, int separator_size, float separator_multiplier, bool is_fullscreen) { + if(!should_have_separator(top_screen_size, bot_screen_size, top_scaling, bot_scaling, stype)) + return 0; + if((bottom_pos != RIGHT_TOP) && (bottom_pos != LEFT_TOP)) + return 0; + return get_separator_size_xy(top_scaling, bot_scaling, separator_size, separator_multiplier, is_fullscreen); +} + +static int get_separator_size_y(sf::Vector2f top_screen_size, sf::Vector2f bot_screen_size, float top_scaling, float bot_scaling, ScreenType stype, BottomRelativePosition bottom_pos, int separator_size, float separator_multiplier, bool is_fullscreen) { + if(!should_have_separator(top_screen_size, bot_screen_size, top_scaling, bot_scaling, stype)) + return 0; + if((bottom_pos != UNDER_TOP) && (bottom_pos != ABOVE_TOP)) + return 0; + return get_separator_size_xy(top_scaling, bot_scaling, separator_size, separator_multiplier, is_fullscreen); +} + +void WindowScreen::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, int separator_size_x, int separator_size_y, bool do_work) { int top_screen_x = 0, top_screen_y = 0; int bot_screen_x = 0, bot_screen_y = 0; int top_screen_width = curr_top_screen_size.x; @@ -707,30 +743,30 @@ void WindowScreen::set_position_screens(sf::Vector2f &curr_top_screen_size, sf:: case UNDER_TOP: bot_screen_x = (greatest_width - bot_screen_width) * this->loaded_info.subscreen_offset; top_screen_x = (greatest_width - top_screen_width) * this->loaded_info.subscreen_offset; - bot_screen_y = top_screen_height; + bot_screen_y = top_screen_height + separator_size_y; if(max_y > 0) - bot_screen_y += (max_y - bot_screen_height - top_screen_height - offset_y) * this->loaded_info.subscreen_attached_offset; + bot_screen_y += (max_y - bot_screen_height - separator_size_y - top_screen_height - offset_y) * this->loaded_info.subscreen_attached_offset; break; case RIGHT_TOP: bot_screen_y = (greatest_height - bot_screen_height) * this->loaded_info.subscreen_offset; top_screen_y = (greatest_height - top_screen_height) * this->loaded_info.subscreen_offset; - bot_screen_x = top_screen_width; + bot_screen_x = top_screen_width + separator_size_x; if(max_x > 0) - bot_screen_x += (max_x - bot_screen_width - top_screen_width - offset_x) * this->loaded_info.subscreen_attached_offset; + bot_screen_x += (max_x - bot_screen_width - separator_size_x - top_screen_width - offset_x) * this->loaded_info.subscreen_attached_offset; break; case ABOVE_TOP: bot_screen_x = (greatest_width - bot_screen_width) * this->loaded_info.subscreen_offset; top_screen_x = (greatest_width - top_screen_width) * this->loaded_info.subscreen_offset; - top_screen_y = bot_screen_height; + top_screen_y = bot_screen_height + separator_size_y; if(max_y > 0) - top_screen_y += (max_y - bot_screen_height - top_screen_height - offset_y) * this->loaded_info.subscreen_attached_offset; + top_screen_y += (max_y - bot_screen_height - separator_size_y - top_screen_height - offset_y) * this->loaded_info.subscreen_attached_offset; break; case LEFT_TOP: bot_screen_y = (greatest_height - bot_screen_height) * this->loaded_info.subscreen_offset; top_screen_y = (greatest_height - top_screen_height) * this->loaded_info.subscreen_offset; - top_screen_x = bot_screen_width; + top_screen_x = bot_screen_width + separator_size_x; if(max_x > 0) - top_screen_x += (max_x - bot_screen_width - top_screen_width - offset_x) * this->loaded_info.subscreen_attached_offset; + top_screen_x += (max_x - bot_screen_width - separator_size_x - top_screen_width - offset_x) * this->loaded_info.subscreen_attached_offset; break; default: break; @@ -754,18 +790,17 @@ 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) { +float WindowScreen::get_max_float_screen_multiplier(ResizingScreenData *own_screen, int width_limit, int height_limit, int other_rotation, bool is_two_screens_merged) { if(!is_size_valid(own_screen->size)) return 0; if((other_rotation / 10) % 2) std::swap(width_limit, height_limit); - int desk_height = curr_desk_mode.size.y; - int desk_width = curr_desk_mode.size.x; + sf::Vector2f other_screen_size = sf::Vector2f(width_limit, height_limit); + if((!is_size_valid(other_screen_size)) && is_two_screens_merged) + other_screen_size = sf::Vector2f(1, 1); + int desk_height = curr_desk_mode.size.y - get_separator_size_y(own_screen->size, other_screen_size, 1.0, 1.0, this->m_stype, this->m_info.bottom_pos, this->m_info.separator_pixel_size, this->m_info.separator_fullscreen_multiplier, true); + int desk_width = curr_desk_mode.size.x - get_separator_size_x(own_screen->size, other_screen_size, 1.0, 1.0, this->m_stype, this->m_info.bottom_pos, this->m_info.separator_pixel_size, this->m_info.separator_fullscreen_multiplier, true); int height_max = desk_height; int width_max = desk_width; switch(this->m_info.bottom_pos) { @@ -781,7 +816,18 @@ float WindowScreen::get_max_float_screen_multiplier(ResizingScreenData *own_scre break; } - return get_par_mult_factor(own_screen->size.x, own_screen->size.y, width_max, height_max, own_screen->par, (own_screen->rotation / 10) % 2); + float own_width = own_screen->size.x; + float own_height = own_screen->size.y; + get_par_size(own_width, own_height, 1.0, own_screen->par); + if((own_screen->rotation / 10) % 2) + std::swap(own_width, own_height); + if((own_height == 0) || (own_width == 0)) + return 0; + float factor_width = width_max / own_width; + float factor_height = height_max / own_height; + if(factor_height < factor_width) + return factor_height; + return factor_width; } int WindowScreen::prepare_screen_ratio(ResizingScreenData *own_screen, int width_limit, int height_limit, int other_rotation) { @@ -992,7 +1038,7 @@ bool WindowScreen::prepare_screens_same_scaling_factor(ResizingScreenData* top_s 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); + non_int_scaling_merged = this->get_max_float_screen_multiplier(&merged_screen_resize_data, 0, 0, 0, true); scaling_merged = non_int_scaling_merged; if(non_int_scaling_merged < 1.0) return false; @@ -1047,14 +1093,12 @@ void WindowScreen::prepare_size_ratios(bool top_increase, bool bot_increase, boo } } -int WindowScreen::get_fullscreen_offset_x(int top_width, int top_height, int bot_width, int bot_height) { +int WindowScreen::get_fullscreen_offset_x(int top_width, int top_height, int bot_width, int bot_height, int separator_contribute) { if((this->loaded_info.top_rotation / 10) % 2) std::swap(top_width, top_height); if((this->loaded_info.bot_rotation / 10) % 2) std::swap(bot_width, bot_height); - int greatest_width = top_width; - if(bot_width > top_width) - greatest_width = bot_width; + int greatest_width = std::max(top_width, bot_width); int offset_contribute = 0; switch(this->loaded_info.bottom_pos) { case UNDER_TOP: @@ -1063,7 +1107,7 @@ int WindowScreen::get_fullscreen_offset_x(int top_width, int top_height, int bot break; case LEFT_TOP: case RIGHT_TOP: - offset_contribute = top_width + bot_width; + offset_contribute = top_width + bot_width + separator_contribute; break; default: return 0; @@ -1071,19 +1115,17 @@ int WindowScreen::get_fullscreen_offset_x(int top_width, int top_height, int bot return (curr_desk_mode.size.x - offset_contribute) * this->loaded_info.total_offset_x; } -int WindowScreen::get_fullscreen_offset_y(int top_width, int top_height, int bot_width, int bot_height) { +int WindowScreen::get_fullscreen_offset_y(int top_width, int top_height, int bot_width, int bot_height, int separator_contribute) { if((this->loaded_info.top_rotation / 10) % 2) std::swap(top_width, top_height); if((this->loaded_info.bot_rotation / 10) % 2) std::swap(bot_width, bot_height); - int greatest_height = top_height; - if(bot_height > top_height) - greatest_height = bot_height; + int greatest_height = std::max(top_height, bot_height); int offset_contribute = 0; switch(this->loaded_info.bottom_pos) { case UNDER_TOP: case ABOVE_TOP: - offset_contribute = top_height + bot_height; + offset_contribute = top_height + bot_height + separator_contribute; break; case LEFT_TOP: case RIGHT_TOP: @@ -1108,10 +1150,14 @@ void WindowScreen::resize_window_and_out_rects(bool do_work) { int offset_y = 0; int max_x = 0; int max_y = 0; + int separator_size_x = 0; + int separator_size_y = 0; + float sep_multiplier = this->loaded_info.separator_windowed_multiplier; if(this->loaded_info.is_fullscreen) { top_scaling = this->loaded_info.non_integer_top_scaling; bot_scaling = this->loaded_info.non_integer_bot_scaling; + sep_multiplier = this->loaded_info.separator_fullscreen_multiplier; } if((this->loaded_info.top_par >= this->possible_pars.size()) || (this->loaded_info.top_par < 0)) this->loaded_info.top_par = 0; @@ -1125,9 +1171,11 @@ void WindowScreen::resize_window_and_out_rects(bool do_work) { offset_x = LEFT_ROUNDED_PADDING; } + separator_size_x = get_separator_size_x(top_screen_size, bot_screen_size, top_scaling, bot_scaling, this->m_stype, this->loaded_info.bottom_pos, this->loaded_info.separator_pixel_size, sep_multiplier, this->loaded_info.is_fullscreen); + separator_size_y = get_separator_size_y(top_screen_size, bot_screen_size, top_scaling, bot_scaling, this->m_stype, this->loaded_info.bottom_pos, this->loaded_info.separator_pixel_size, sep_multiplier, this->loaded_info.is_fullscreen); if(this->loaded_info.is_fullscreen) { - offset_x = get_fullscreen_offset_x(top_width, top_height, bot_width, bot_height); - offset_y = get_fullscreen_offset_y(top_width, top_height, bot_width, bot_height); + offset_x = get_fullscreen_offset_x(top_width, top_height, bot_width, bot_height, separator_size_x); + offset_y = get_fullscreen_offset_y(top_width, top_height, bot_width, bot_height, separator_size_y); max_x = curr_desk_mode.size.x; max_y = curr_desk_mode.size.y; } @@ -1139,7 +1187,7 @@ void WindowScreen::resize_window_and_out_rects(bool do_work) { this->m_out_rect_bot.out_rect.setSize(new_bot_screen_size); this->m_out_rect_bot.out_rect.setTextureRect(sf::IntRect({0, 0}, {(int)bot_screen_size.x, (int)bot_screen_size.y})); } - this->set_position_screens(new_top_screen_size, new_bot_screen_size, offset_x, offset_y, max_x, max_y, do_work); + this->set_position_screens(new_top_screen_size, new_bot_screen_size, offset_x, offset_y, max_x, max_y, separator_size_x, separator_size_y, do_work); if((!this->loaded_info.is_fullscreen) && this->loaded_info.rounded_corners_fix) { this->m_height += BOTTOM_ROUNDED_PADDING; this->m_width += RIGHT_ROUNDED_PADDING; diff --git a/source/WindowScreen_Menu.cpp b/source/WindowScreen_Menu.cpp index 98ae8e1..5726983 100755 --- a/source/WindowScreen_Menu.cpp +++ b/source/WindowScreen_Menu.cpp @@ -118,6 +118,7 @@ void WindowScreen::init_menus() { this->video_effects_menu = new VideoEffectsMenu(this->font_load_success, this->text_font); this->input_menu = new InputMenu(this->font_load_success, this->text_font); this->audio_device_menu = new AudioDeviceMenu(this->font_load_success, this->text_font); + this->separator_menu = new SeparatorMenu(this->font_load_success, this->text_font); } void WindowScreen::destroy_menus() { @@ -143,6 +144,7 @@ void WindowScreen::destroy_menus() { delete this->video_effects_menu; delete this->input_menu; delete this->audio_device_menu; + delete this->separator_menu; } void WindowScreen::set_close(int ret_val) { @@ -378,7 +380,7 @@ void WindowScreen::rotation_change(int &value, bool right) { 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->prepare_size_ratios(true, true); this->future_operations.call_screen_settings_update = true; } @@ -453,6 +455,51 @@ void WindowScreen::frame_blending_mode_change(bool positive) { this->m_info.frame_blending_bot = this->m_info.frame_blending_top; } +void WindowScreen::separator_size_change(int change) { + if(this->m_stype != ScreenType::JOINT) + return; + int new_size = this->m_info.separator_pixel_size + change; + if(new_size < 0) + new_size = 0; + if(new_size > MAX_SEP_SIZE) + new_size = MAX_SEP_SIZE; + if(new_size != this->m_info.separator_pixel_size) { + this->m_info.separator_pixel_size = new_size; + this->prepare_size_ratios(true, true); + this->future_operations.call_screen_settings_update = true; + } +} + +void WindowScreen::separator_multiplier_change(bool positive, float& multiplier_to_check, float lower_limit, float upper_limit) { + if(this->m_stype != ScreenType::JOINT) + return; + float change = WINDOW_SCALING_CHANGE; + if(!positive) + change = -WINDOW_SCALING_CHANGE; + float new_value = multiplier_to_check + change; + if(new_value < lower_limit) + new_value = lower_limit; + if(new_value > upper_limit) + new_value = upper_limit; + if(new_value != multiplier_to_check) { + multiplier_to_check = new_value; + this->prepare_size_ratios(true, true); + this->future_operations.call_screen_settings_update = true; + } +} + +void WindowScreen::separator_windowed_multiplier_change(bool positive) { + if(this->m_info.is_fullscreen) + return; + this->separator_multiplier_change(positive, this->m_info.separator_windowed_multiplier, SEP_WINDOW_SCALING_MIN_MULTIPLIER, MAX_WINDOW_SCALING_VALUE); +} + +void WindowScreen::separator_fullscreen_multiplier_change(bool positive) { + if(!this->m_info.is_fullscreen) + return; + this->separator_multiplier_change(positive, this->m_info.separator_fullscreen_multiplier, SEP_FULLSCREEN_SCALING_MIN_MULTIPLIER, MAX_WINDOW_SCALING_VALUE); +} + bool WindowScreen::can_execute_cmd(const WindowCommand* window_cmd, bool is_extra, bool is_always) { if((!window_cmd->usable_always) && is_always) return false; @@ -1056,6 +1103,18 @@ void WindowScreen::setup_video_effects_menu(bool reset_data) { } } +void WindowScreen::setup_separator_menu(bool reset_data) { + if(!this->can_setup_menu()) + return; + if(this->curr_menu != SEPARATOR_MENU_TYPE) { + this->curr_menu = SEPARATOR_MENU_TYPE; + if(reset_data) + this->separator_menu->reset_data(); + this->separator_menu->insert_data(this->m_info.is_fullscreen); + this->last_menu_change_time = std::chrono::high_resolution_clock::now(); + } +} + void WindowScreen::update_save_menu() { if(this->curr_menu == SAVE_MENU_TYPE) { this->curr_menu = DEFAULT_MENU_TYPE; @@ -1594,6 +1653,9 @@ void WindowScreen::poll(bool do_everything) { case VIDEO_MENU_VIDEO_EFFECTS_SETTINGS: this->setup_video_effects_menu(); break; + case VIDEO_MENU_SEPARATOR_SETTINGS: + this->setup_separator_menu(); + break; default: break; } @@ -2070,6 +2132,46 @@ void WindowScreen::poll(bool do_everything) { continue; } break; + case SEPARATOR_MENU_TYPE: + if(this->separator_menu->poll(event_data)) { + switch(this->separator_menu->selected_index) { + case SEPARATOR_MENU_BACK: + this->setup_video_menu(false); + done = true; + break; + case SEPARATOR_MENU_NO_ACTION: + break; + case SEPARATOR_MENU_SIZE_DEC_1: + this->separator_size_change(-1); + break; + case SEPARATOR_MENU_SIZE_INC_1: + this->separator_size_change(1); + break; + case SEPARATOR_MENU_SIZE_DEC_10: + this->separator_size_change(-10); + break; + case SEPARATOR_MENU_SIZE_INC_10: + this->separator_size_change(10); + break; + case SEPARATOR_MENU_WINDOW_MUL_DEC: + this->separator_windowed_multiplier_change(false); + break; + case SEPARATOR_MENU_WINDOW_MUL_INC: + this->separator_windowed_multiplier_change(true); + break; + case SEPARATOR_MENU_FULLSCREEN_MUL_DEC: + this->separator_fullscreen_multiplier_change(false); + break; + case SEPARATOR_MENU_FULLSCREEN_MUL_INC: + this->separator_fullscreen_multiplier_change(true); + break; + default: + break; + } + this->separator_menu->reset_output_option(); + continue; + } + break; default: break; } @@ -2346,6 +2448,9 @@ void WindowScreen::prepare_menu_draws(int view_size_x, int view_size_y) { case AUDIO_DEVICE_MENU_TYPE: this->audio_device_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, this->audio_data->get_audio_output_device_data()); break; + case SEPARATOR_MENU_TYPE: + this->separator_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, &this->loaded_info); + break; default: break; } @@ -2425,6 +2530,9 @@ void WindowScreen::execute_menu_draws() { case AUDIO_DEVICE_MENU_TYPE: this->audio_device_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win); break; + case SEPARATOR_MENU_TYPE: + this->separator_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win); + break; default: break; } diff --git a/source/frontend.cpp b/source/frontend.cpp index 34a4329..cc9766d 100755 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -1,5 +1,5 @@ #include "frontend.hpp" -#include +#include #include #include @@ -464,6 +464,9 @@ void reset_screen_info(ScreenInfo &info) { info.window_enabled = false; info.initial_pos_x = DEFAULT_NO_POS_WINDOW_VALUE; info.initial_pos_y = DEFAULT_NO_POS_WINDOW_VALUE; + info.separator_pixel_size = DEFAULT_SEP_SIZE; + info.separator_windowed_multiplier = SEP_FOLLOW_SCALING_MULTIPLIER; + info.separator_fullscreen_multiplier = DEFAULT_WINDOW_SCALING_VALUE; } void override_set_data_to_screen_info(override_win_data &override_win, ScreenInfo &info) { @@ -612,6 +615,32 @@ bool load_screen_info(std::string key, std::string value, std::string base, Scre info.force_same_scaling = std::stoi(value); return true; } + if(key == (base + "separator_pixel_size")) { + info.separator_pixel_size = std::stoi(value); + if(info.separator_pixel_size > MAX_SEP_SIZE) + info.separator_pixel_size = MAX_SEP_SIZE; + if(info.separator_pixel_size < 0) + info.separator_pixel_size = 0; + return true; + } + if(key == (base + "separator_windowed_multiplier")) { + info.separator_windowed_multiplier = std::stof(value); + if(info.separator_windowed_multiplier < SEP_WINDOW_SCALING_MIN_MULTIPLIER) + info.separator_windowed_multiplier = SEP_WINDOW_SCALING_MIN_MULTIPLIER; + if(info.separator_windowed_multiplier > MAX_WINDOW_SCALING_VALUE) + info.separator_windowed_multiplier = MAX_WINDOW_SCALING_VALUE; + info.separator_windowed_multiplier = std::round(info.separator_windowed_multiplier / WINDOW_SCALING_CHANGE) * WINDOW_SCALING_CHANGE; + return true; + } + if(key == (base + "separator_fullscreen_multiplier")) { + info.separator_fullscreen_multiplier = std::stof(value); + if(info.separator_fullscreen_multiplier < SEP_FULLSCREEN_SCALING_MIN_MULTIPLIER) + info.separator_fullscreen_multiplier = SEP_FULLSCREEN_SCALING_MIN_MULTIPLIER; + if(info.separator_fullscreen_multiplier > MAX_WINDOW_SCALING_VALUE) + info.separator_fullscreen_multiplier = MAX_WINDOW_SCALING_VALUE; + info.separator_fullscreen_multiplier = std::round(info.separator_fullscreen_multiplier / WINDOW_SCALING_CHANGE) * WINDOW_SCALING_CHANGE; + return true; + } if(key == (base + "top_par")) { info.top_par = std::stoi(value); return true; @@ -713,6 +742,9 @@ std::string save_screen_info(std::string base, const ScreenInfo &info) { 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"; + out += base + "separator_pixel_size=" + std::to_string(info.separator_pixel_size) + "\n"; + out += base + "separator_windowed_multiplier=" + std::to_string(info.separator_windowed_multiplier) + "\n"; + out += base + "separator_fullscreen_multiplier=" + std::to_string(info.separator_fullscreen_multiplier) + "\n"; return out; } @@ -773,43 +805,6 @@ void get_par_size(float &width, float &height, float multiplier_factor, const PA } } -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; - if(correction_factor->is_width_main) { - correction_factor_divisor = correction_factor->width_divisor; - correction_factor_multiplier = correction_factor->width_multiplier; - } - if(correction_factor->is_fit) { - if(correction_factor->is_width_main) - width = height * correction_factor_multiplier; - else - height = width * correction_factor_multiplier; - } - else { - if(correction_factor->is_width_main) - width = width * correction_factor_multiplier; - else - height = height * correction_factor_multiplier; - } - bool apply_to_max_width = correction_factor->is_width_main; - if(is_rotated) { - std::swap(width, height); - apply_to_max_width = !apply_to_max_width; - } - if(apply_to_max_width) - max_width = max_width * correction_factor_divisor; - else - max_height = max_height * correction_factor_divisor; - if((height == 0) || (width == 0)) - return 0; - float factor_width = max_width / width; - float factor_height = max_height / height; - if(factor_height < factor_width) - return factor_height; - return factor_width; -} - JoystickDirection get_joystick_direction(uint32_t joystickId, sf::Joystick::Axis axis, float position) { bool is_horizontal = false; if((axis == sf::Joystick::Axis::Z) || (axis == sf::Joystick::Axis::R))