Add N3DS XL Loopy 3D Mode
Some checks are pending
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux32 flags:32 name:Linux GCC 32 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux64 flags:64 name:Linux GCC x64 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm32 flags:arm32 name:Linux GCC ARM 32 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm64 flags:arm64 name:Linux GCC ARM 64 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:macos name:macOS Apple Silicon os:macos-14]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win32 flags:-A Win32 name:Windows VS2022 Win32 os:windows-2022]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win64 flags:-A x64 name:Windows VS2022 x64 os:windows-2022]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:winarm64 flags:-A ARM64 name:Windows VS2022 ARM os:windows-2022]) (push) Waiting to run
CD / Create Pi Mono Setup (push) Blocked by required conditions
CD / Publishing (push) Blocked by required conditions

This commit is contained in:
Lorenzooone
2025-03-23 23:27:05 +01:00
parent 1e50e5d353
commit 642a9cfb79
24 changed files with 1213 additions and 149 deletions

View File

@@ -525,7 +525,7 @@ if(MSVC)
else()
set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "$<$<CONFIG:Release>:-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 source/Menus/SeparatorMenu.cpp source/Menus/ColorCorrectionMenu.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 source/Menus/ColorCorrectionMenu.cpp source/Menus/Main3DMenu.cpp source/Menus/SecondScreen3DRelativePositionMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES})
if(NOT ("${EXTRA_DEPENDENCIES}" STREQUAL ""))

View File

@@ -5,9 +5,11 @@
#include <chrono>
#include "capture_structs.hpp"
uint64_t ftd3_get_capture_size(bool is_3d_enabled);
uint64_t ftd3_get_capture_size(CaptureData* capture_data);
std::string ftd3_get_serial(std::string serial_string, int &curr_serial_extra_id);
void ftd3_insert_device(std::vector<CaptureDevice> &devices_list, std::string serial_string, int &curr_serial_extra_id, uint32_t usb_speed, bool is_driver);
void data_output_update(int inner_index, size_t read_data, CaptureData* capture_data, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time);
bool ftd3_capture_3d_setup(CaptureData* capture_data, bool first_pass, bool& stored_3d_status);
#endif

View File

@@ -0,0 +1,44 @@
#ifndef __MAIN3DMENU_HPP
#define __MAIN3DMENU_HPP
#include "OptionSelectionMenu.hpp"
#include <chrono>
#include "TextRectangle.hpp"
#include "sfml_gfx_structs.hpp"
#include "display_structs.hpp"
#include "capture_structs.hpp"
enum Main3DMenuOutAction{
MAIN_3D_MENU_NO_ACTION,
MAIN_3D_MENU_BACK,
MAIN_3D_MENU_REQUEST_3D_TOGGLE,
MAIN_3D_MENU_INTERLEAVED_TOGGLE,
MAIN_3D_MENU_SQUISH_TOP_TOGGLE,
MAIN_3D_MENU_SQUISH_BOTTOM_TOGGLE,
MAIN_3D_MENU_USB_SPEED_INFO,
MAIN_3D_MENU_DEVICE_INFO,
MAIN_3D_MENU_IMPLEMENTATION_INFO,
MAIN_3D_MENU_SECOND_SCREEN_POSITION_SETTINGS,
};
class Main3DMenu : public OptionSelectionMenu {
public:
Main3DMenu(bool font_load_success, sf::Font &text_font);
~Main3DMenu();
void prepare(float menu_scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info, DisplayData* display_data, CaptureStatus* status);
void insert_data(ScreenType stype);
Main3DMenuOutAction selected_index = Main3DMenuOutAction::MAIN_3D_MENU_NO_ACTION;
void reset_output_option();
protected:
bool is_option_selectable(int index, int action);
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;
};
#endif

View File

@@ -18,6 +18,7 @@ enum RelPosMenuOutAction{
class RelativePositionMenu {
public:
RelativePositionMenu();
RelativePositionMenu(bool font_load_success, sf::Font &text_font);
~RelativePositionMenu();
bool poll(SFEvent &event_data);
@@ -29,7 +30,7 @@ public:
void insert_data();
RelPosMenuOutAction selected_index = RelPosMenuOutAction::REL_POS_MENU_NO_ACTION;
BottomRelativePosition selected_confirm_value = BOT_REL_POS_END;
private:
protected:
struct RelPosMenuData {
int option_selected = -1;
int menu_width;
@@ -39,7 +40,11 @@ private:
};
RelPosMenuData future_data;
TextRectangle **labels;
bool *selectable_labels;
int num_vertical_slices;
int num_elements_per_screen;
int num_elements_displayed_per_screen;
int num_options_per_screen;
int elements_start_id;
int min_elements_text_scaling_factor;
@@ -52,10 +57,23 @@ private:
sf::Color menu_color;
std::string title;
int num_elements_per_screen;
void initialize(bool font_load_success, sf::Font &text_font);
void prepare_options();
void base_prepare(float menu_scaling_factor, int view_size_x, int view_size_y);
void prepare_text_slices(int x_multiplier, int x_divisor, int y_multiplier, int y_divisor, int index, float text_scaling_factor, bool center = false);
virtual bool is_option_selectable(int index);
virtual void set_output_option(int index);
virtual std::string get_string_option(int index);
virtual void class_setup();
virtual void option_slice_prepare(int i, int index, int num_vertical_slices, float text_scaling_factor);
virtual bool is_option_element(int option);
virtual bool is_option_left(int index);
virtual bool is_option_right(int index);
virtual bool is_option_above(int index);
virtual bool is_option_below(int index);
private:
int num_title_back_x_elements;
int num_elements_displayed_per_screen;
int num_vertical_slices;
int title_back_x_start_id;
int back_x_id;
int title_id;
@@ -63,26 +81,16 @@ private:
std::chrono::time_point<std::chrono::high_resolution_clock> last_action_time;
const float action_timeout = 0.1;
int option_selected = -1;
bool *selectable_labels;
RelPosMenuData loaded_data;
sf::RectangleShape menu_rectangle = sf::RectangleShape(sf::Vector2f(1, 1));
bool is_option_selectable(int index);
void set_output_option(int index);
std::string get_string_option(int index);
void class_setup();
void prepare_options();
void base_prepare(float menu_scaling_factor, int view_size_x, int view_size_y);
void after_class_setup_connected_values();
void prepare_text_slices(int x_multiplier, int x_divisor, int y_multiplier, int y_divisor, int index, float text_scaling_factor, bool center = false);
bool can_execute_action();
void up_code(bool is_simple);
void down_code(bool is_simple);
void left_code();
void right_code();
void option_selection_handling();
bool is_option_element(int option);
void set_default_cursor_position();
void decrement_selected_option(bool is_simple);
void increment_selected_option(bool is_simple);

View File

@@ -0,0 +1,48 @@
#ifndef __SECOND_SCREEN_3D_RELPOSMENU_HPP
#define __SECOND_SCREEN_3D_RELPOSMENU_HPP
#include <SFML/Graphics.hpp>
#include <chrono>
#include "TextRectangle.hpp"
#include "display_structs.hpp"
#include "event_structs.hpp"
#include "RelativePositionMenu.hpp"
#define BACK_X_OUTPUT_OPTION -1
enum SecondScreen3DRelPosMenuOutAction{
SECOND_SCREEN_3D_REL_POS_MENU_NO_ACTION,
SECOND_SCREEN_3D_REL_POS_MENU_BACK,
SECOND_SCREEN_3D_REL_POS_MENU_TOGGLE_MATCH,
SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM,
};
class SecondScreen3DRelativePositionMenu : public RelativePositionMenu {
public:
SecondScreen3DRelativePositionMenu(bool font_load_success, sf::Font &text_font);
~SecondScreen3DRelativePositionMenu();
std::chrono::time_point<std::chrono::high_resolution_clock> last_input_processed_time;
void reset_output_option();
void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo* info);
void insert_data(ScreenType stype);
SecondScreen3DRelPosMenuOutAction selected_index = SecondScreen3DRelPosMenuOutAction::SECOND_SCREEN_3D_REL_POS_MENU_NO_ACTION;
SecondScreen3DRelativePosition selected_confirm_value = SECOND_SCREEN_3D_REL_POS_END;
protected:
bool is_option_selectable(int index);
void set_output_option(int index);
std::string get_string_option(int index);
void class_setup();
void option_slice_prepare(int i, int index, int num_vertical_slices, float text_scaling_factor);
bool is_option_element(int option);
bool is_option_left(int index);
bool is_option_right(int index);
bool is_option_above(int index);
bool is_option_below(int index);
private:
std::string setTextOptionBool(int index, bool value);
std::string get_false_option(int index);
int pos_y_subtractor;
};
#endif

View File

@@ -41,6 +41,7 @@ enum VideoMenuOutAction{
VIDEO_MENU_CHANGE_TITLEBAR,
VIDEO_MENU_VIDEO_EFFECTS_SETTINGS,
VIDEO_MENU_SEPARATOR_SETTINGS,
VIDEO_MENU_3D_SETTINGS,
};
class VideoMenu : public OptionSelectionMenu {

View File

@@ -27,5 +27,7 @@ std::string get_name_of_device(CaptureStatus* capture_status, bool use_long = fa
int get_usb_speed_of_device(CaptureStatus* capture_status);
bool get_device_can_do_3d(CaptureStatus* capture_status);
bool get_device_3d_implemented(CaptureStatus* capture_status);
bool get_3d_enabled(CaptureStatus* capture_status);
bool is_usb_speed_of_device_enough_3d(CaptureStatus* capture_status);
bool get_3d_enabled(CaptureStatus* capture_status, bool skip_requested_3d_check = false);
bool update_3d_enabled(CaptureStatus* capture_status);
#endif

View File

@@ -24,8 +24,9 @@
enum ScreenType { TOP, BOTTOM, JOINT };
enum BottomRelativePosition { UNDER_TOP, LEFT_TOP, ABOVE_TOP, RIGHT_TOP, BOT_REL_POS_END };
enum SecondScreen3DRelativePosition { UNDER_FIRST, LEFT_FIRST, ABOVE_FIRST, RIGHT_FIRST, SECOND_SCREEN_3D_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, SEPARATOR_MENU_TYPE, COLOR_CORRECTION_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, COLOR_CORRECTION_MENU_TYPE, MAIN_3D_MENU_TYPE, SECOND_SCREEN_RELATIVE_POS_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 +45,8 @@ struct ScreenInfo {
double scaling;
bool is_fullscreen;
BottomRelativePosition bottom_pos;
SecondScreen3DRelativePosition second_screen_pos;
bool match_bottom_pos_and_second_screen_pos;
float subscreen_offset, subscreen_attached_offset, total_offset_x, total_offset_y;
int top_rotation, bot_rotation;
bool show_mouse;
@@ -76,6 +79,8 @@ struct ScreenInfo {
InputColorspaceMode in_colorspace_bot;
FrameBlendingMode frame_blending_top;
FrameBlendingMode frame_blending_bot;
bool squish_3d_top;
bool squish_3d_bot;
bool window_enabled;
int initial_pos_x;
int initial_pos_y;

View File

@@ -36,6 +36,8 @@
#include "AudioDeviceMenu.hpp"
#include "SeparatorMenu.hpp"
#include "ColorCorrectionMenu.hpp"
#include "Main3DMenu.hpp"
#include "SecondScreen3DRelativePositionMenu.hpp"
#include "display_structs.hpp"
#include "event_structs.hpp"
#include "shaders_list.hpp"
@@ -99,16 +101,20 @@ private:
bool use_non_int_scaling;
int rotation;
const PARData *par;
bool divide_3d_par;
};
bool created_proper_folder;
CaptureStatus* capture_status;
std::string win_title;
sf::RenderWindow m_win;
int m_width, m_height;
int m_width_no_manip, m_height_no_manip;
int m_window_width, m_window_height;
int m_prepare_load;
int m_prepare_save;
bool last_connected_status;
bool last_enabled_3d;
bool last_interleaved_3d;
bool m_prepare_open;
bool m_prepare_quit;
bool m_scheduled_split;
@@ -160,6 +166,8 @@ private:
AudioDeviceMenu *audio_device_menu;
SeparatorMenu *separator_menu;
ColorCorrectionMenu *color_correction_menu;
Main3DMenu *main_3d_menu;
SecondScreen3DRelativePositionMenu *second_screen_3d_relpos_menu;
std::vector<const CropData*> possible_crops;
std::vector<const CropData*> possible_crops_ds;
std::vector<const CropData*> possible_crops_with_games;
@@ -192,8 +200,8 @@ private:
volatile bool is_thread_done;
bool was_last_frame_null;
sf::RectangleShape m_in_rect_top, m_in_rect_bot;
out_rect_data m_out_rect_top, m_out_rect_bot;
sf::RectangleShape m_in_rect_top, m_in_rect_bot, m_in_rect_top_right;
out_rect_data m_out_rect_top, m_out_rect_bot, m_out_rect_top_right;
ScreenType m_stype;
const ShaderColorEmulationData* sent_shader_color_data;
@@ -237,6 +245,9 @@ private:
void fast_poll_change();
void padding_change();
void game_crop_enable_change();
void request_3d_change();
void interleaved_3d_change();
void squish_3d_change(bool is_top);
void audio_device_change(audio_output_device_data new_device_data);
void is_nitro_capture_type_change(bool positive);
void is_nitro_capture_speed_change(bool positive);
@@ -264,6 +275,8 @@ private:
void separator_windowed_multiplier_change(bool positive);
void separator_fullscreen_multiplier_change(bool positive);
void color_correction_value_change(int new_color_correction_value);
void second_screen_3d_pos_change(int new_second_screen_3d_pos);
void second_screen_3d_match_bottom_pos_change();
bool query_reset_request();
void reset_held_times(bool force = true);
void poll_window(bool do_everything);
@@ -278,16 +291,20 @@ private:
int _choose_color_emulation_shader(bool is_top);
int _choose_shader(PossibleShaderTypes shader_type, bool is_top);
int choose_shader(PossibleShaderTypes shader_type, bool is_top);
void apply_shader_to_texture(out_rect_data &rect_data, PossibleShaderTypes shader_type, bool is_top);
bool apply_shaders_to_input(out_rect_data &rect_data, const sf::RectangleShape &final_in_rect, bool is_top);
void apply_shader_to_texture(sf::RectangleShape &rect_data, sf::RenderTexture &tex_data, PossibleShaderTypes shader_type, bool is_top);
bool apply_shaders_to_input(sf::RectangleShape &rect_data, sf::RenderTexture &tex_data, const sf::RectangleShape &final_in_rect, bool is_top);
void pre_texture_conversion_processing();
void post_texture_conversion_processing(out_rect_data &rect_data, const sf::RectangleShape &in_rect, bool actually_draw, bool is_top, bool is_debug);
void post_texture_conversion_processing(sf::RectangleShape &rect_data, sf::RenderTexture &tex_data, const sf::RectangleShape &in_rect, bool actually_draw, bool is_top, bool is_debug);
void draw_rect_to_window(const sf::RectangleShape &out_rect, bool is_top);
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, 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);
bool get_divide_3d_par(bool is_top, ScreenInfo* info);
sf::Vector2u get_3d_size_multiplier(ScreenInfo* info);
sf::Vector2u get_desk_mode_3d_multiplied(ScreenInfo* info);
sf::Vector2f get_3d_offset_out_rect(ScreenInfo* info, bool is_second_screen);
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();
@@ -339,6 +356,8 @@ private:
void setup_input_menu(bool reset_data = true);
void setup_separator_menu(bool reset_data = true);
void setup_color_correction_menu(bool reset_data = true);
void setup_main_3d_menu(bool reset_data = true);
void setup_second_screen_3d_relpos_menu(bool reset_data = true);
void update_connection();
};
@@ -367,8 +386,9 @@ 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);
void get_par_size(int &width, int &height, float multiplier_factor, const PARData *correction_factor, bool divide_3d_par);
void get_par_size(float &width, float &height, float multiplier_factor, const PARData *correction_factor, bool divide_3d_par);
SecondScreen3DRelativePosition get_second_screen_pos(ScreenInfo* info, ScreenType stype);
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);

View File

@@ -21,9 +21,44 @@ struct FTD3XXReceivedDataBuffer {
ULONG read_buffer;
};
static bool wait_all_fast_capture_call_async_transfers(FTD3XXReceivedDataBuffer* received_buffer, CaptureData* capture_data) {
void* handle = ((ftd3_device_device_handlers*)capture_data->handle)->driver_handle;
for(int inner_curr_in = 0; inner_curr_in < FTD3_CONCURRENT_BUFFERS; ++inner_curr_in) {
FT_STATUS ftStatus = FT_GetOverlappedResult(handle, &received_buffer[inner_curr_in].overlap, &received_buffer[inner_curr_in].read_buffer, true);
if(FT_FAILED(ftStatus)) {
capture_error_print(true, capture_data, "Disconnected: USB error");
return false;
}
}
return true;
}
static bool fast_capture_call_init_async_transfers(FTD3XXReceivedDataBuffer* received_buffer, CaptureData* capture_data, int fifo_channel, int &inner_curr_in, bool could_use_3d, bool stored_3d_status) {
void* handle = ((ftd3_device_device_handlers*)capture_data->handle)->driver_handle;
for(inner_curr_in = 0; inner_curr_in < FTD3_CONCURRENT_BUFFERS - 1; ++inner_curr_in) {
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(inner_curr_in);
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
FT_STATUS ftStatus = FT_ASYNC_CALL(handle, fifo_channel, buffer, ftd3_get_capture_size(could_use_3d && stored_3d_status), &received_buffer[inner_curr_in].read_buffer, &received_buffer[inner_curr_in].overlap);
if(ftStatus != FT_IO_PENDING) {
capture_error_print(true, capture_data, "Disconnected: Read failed");
return false;
}
}
inner_curr_in = FTD3_CONCURRENT_BUFFERS - 1;
return true;
}
static void fast_capture_call(FTD3XXReceivedDataBuffer* received_buffer, CaptureData* capture_data, int fifo_channel) {
int inner_curr_in = 0;
FT_STATUS ftStatus;
bool could_use_3d = get_3d_enabled(&capture_data->status, true);
bool stored_3d_status = true;
bool result_3d_setup = ftd3_capture_3d_setup(capture_data, true, stored_3d_status);
if(!result_3d_setup)
return;
void* handle = ((ftd3_device_device_handlers*)capture_data->handle)->driver_handle;
for (inner_curr_in = 0; inner_curr_in < FTD3_CONCURRENT_BUFFERS; ++inner_curr_in) {
ftStatus = FT_InitializeOverlapped(handle, &received_buffer[inner_curr_in].overlap);
@@ -33,24 +68,29 @@ static void fast_capture_call(FTD3XXReceivedDataBuffer* received_buffer, Capture
}
}
for (inner_curr_in = 0; inner_curr_in < FTD3_CONCURRENT_BUFFERS - 1; ++inner_curr_in) {
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(inner_curr_in);
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
ftStatus = FT_ASYNC_CALL(handle, fifo_channel, buffer, ftd3_get_capture_size(capture_data), &received_buffer[inner_curr_in].read_buffer, &received_buffer[inner_curr_in].overlap);
if(ftStatus != FT_IO_PENDING) {
capture_error_print(true, capture_data, "Disconnected: Read failed");
return;
}
}
inner_curr_in = FTD3_CONCURRENT_BUFFERS - 1;
if(!fast_capture_call_init_async_transfers(received_buffer, capture_data, fifo_channel, inner_curr_in, could_use_3d, stored_3d_status))
return;
auto clock_start = std::chrono::high_resolution_clock::now();
while (capture_data->status.connected && capture_data->status.running) {
if(could_use_3d && (stored_3d_status != capture_data->status.requested_3d)) {
if(!wait_all_fast_capture_call_async_transfers(received_buffer, capture_data))
return;
result_3d_setup = ftd3_capture_3d_setup(capture_data, false, stored_3d_status);
if(!result_3d_setup)
return;
if(!fast_capture_call_init_async_transfers(received_buffer, capture_data, fifo_channel, inner_curr_in, could_use_3d, stored_3d_status))
return;
clock_start = std::chrono::high_resolution_clock::now();
}
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(inner_curr_in);
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
ftStatus = FT_ASYNC_CALL(handle, fifo_channel, buffer, ftd3_get_capture_size(capture_data), &received_buffer[inner_curr_in].read_buffer, &received_buffer[inner_curr_in].overlap);
ftStatus = FT_ASYNC_CALL(handle, fifo_channel, buffer, ftd3_get_capture_size(could_use_3d && stored_3d_status), &received_buffer[inner_curr_in].read_buffer, &received_buffer[inner_curr_in].overlap);
if(ftStatus != FT_IO_PENDING) {
capture_error_print(true, capture_data, "Disconnected: Read failed");
return;
@@ -71,15 +111,25 @@ static void fast_capture_call(FTD3XXReceivedDataBuffer* received_buffer, Capture
static bool safe_capture_call(FTD3XXReceivedDataBuffer* received_buffer, CaptureData* capture_data, int fifo_channel) {
auto clock_start = std::chrono::high_resolution_clock::now();
void* handle = ((ftd3_device_device_handlers*)capture_data->handle)->driver_handle;
bool could_use_3d = get_3d_enabled(&capture_data->status, true);
bool stored_3d_status = true;
bool result_3d_setup = ftd3_capture_3d_setup(capture_data, true, stored_3d_status);
if(!result_3d_setup)
return true;
while(capture_data->status.connected && capture_data->status.running) {
if(could_use_3d && (stored_3d_status != capture_data->status.requested_3d)) {
result_3d_setup = ftd3_capture_3d_setup(capture_data, false, stored_3d_status);
if(!result_3d_setup)
return true;
}
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(0);
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
#ifdef _WIN32
FT_STATUS ftStatus = FT_ReadPipeEx(handle, fifo_channel, buffer, ftd3_get_capture_size(capture_data), &received_buffer->read_buffer, NULL);
FT_STATUS ftStatus = FT_ReadPipeEx(handle, fifo_channel, buffer, ftd3_get_capture_size(could_use_3d && stored_3d_status), &received_buffer->read_buffer, NULL);
#else
FT_STATUS ftStatus = FT_ReadPipeEx(handle, fifo_channel, buffer, ftd3_get_capture_size(capture_data), &received_buffer->read_buffer, 1000);
FT_STATUS ftStatus = FT_ReadPipeEx(handle, fifo_channel, buffer, ftd3_get_capture_size(could_use_3d && stored_3d_status), &received_buffer->read_buffer, 1000);
#endif
if(FT_FAILED(ftStatus)) {
capture_error_print(true, capture_data, "Disconnected: Read failed");

View File

@@ -22,6 +22,7 @@
struct FTD3LibusbCaptureReceivedData {
bool in_use;
bool* pause_output;
uint32_t index;
int internal_index;
CaptureData* capture_data;
@@ -105,6 +106,9 @@ static void ftd3_libusb_read_frame_cb(void* user_data, int transfer_length, int
}
*ftd3_libusb_capture_recv_data->last_index = ftd3_libusb_capture_recv_data->index;
if(*ftd3_libusb_capture_recv_data->pause_output)
return end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data, true);
data_output_update(ftd3_libusb_capture_recv_data->internal_index, transfer_length, ftd3_libusb_capture_recv_data->capture_data, *ftd3_libusb_capture_recv_data->clock_start);
end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data, false);
}
@@ -193,10 +197,34 @@ static void ftd3_libusb_capture_main_loop_processing(FTD3LibusbCaptureReceivedDa
int index = 0;
CaptureData* capture_data = ftd3_libusb_capture_recv_data[0].capture_data;
bool could_use_3d = get_3d_enabled(&capture_data->status, true);
bool stored_3d_status = true;
bool result_3d_setup = ftd3_capture_3d_setup(capture_data, true, stored_3d_status);
if(!result_3d_setup)
return;
for(int i = 0; i < FTD3_CONCURRENT_BUFFERS; i++)
ftd3_libusb_read_frame_request(capture_data, ftd3_libusb_get_free_buffer(ftd3_libusb_capture_recv_data), index++, pipe);
while(capture_data->status.connected && capture_data->status.running) {
if(could_use_3d && (stored_3d_status != capture_data->status.requested_3d)) {
*ftd3_libusb_capture_recv_data->pause_output = true;
wait_all_ftd3_libusb_buffers_free(ftd3_libusb_capture_recv_data);
if(get_ftd3_libusb_status(ftd3_libusb_capture_recv_data) < 0) {
capture_error_print(true, capture_data, "Disconnected: Read failed");
return;
}
result_3d_setup = ftd3_capture_3d_setup(capture_data, false, stored_3d_status);
if(!result_3d_setup)
return;
*ftd3_libusb_capture_recv_data->pause_output = false;
for(int i = 0; i < FTD3_CONCURRENT_BUFFERS; i++)
ftd3_libusb_read_frame_request(capture_data, ftd3_libusb_get_free_buffer(ftd3_libusb_capture_recv_data), index++, pipe);
*ftd3_libusb_capture_recv_data[0].clock_start = std::chrono::high_resolution_clock::now();
}
if(get_ftd3_libusb_status(ftd3_libusb_capture_recv_data) < 0) {
capture_error_print(true, capture_data, "Disconnected: Read failed");
return;
@@ -214,12 +242,14 @@ void ftd3_libusb_capture_main_loop(CaptureData* capture_data, int pipe) {
uint32_t last_index = -1;
int status = 0;
bool pause_output = false;
SharedConsumerMutex is_buffer_free_shared_mutex(FTD3_CONCURRENT_BUFFERS);
std::chrono::time_point<std::chrono::high_resolution_clock> clock_start = std::chrono::high_resolution_clock::now();
FTD3LibusbCaptureReceivedData* ftd3_libusb_capture_recv_data = new FTD3LibusbCaptureReceivedData[FTD3_CONCURRENT_BUFFERS];
for(int i = 0; i < FTD3_CONCURRENT_BUFFERS; i++) {
ftd3_libusb_capture_recv_data[i].in_use = false;
ftd3_libusb_capture_recv_data[i].index = i;
ftd3_libusb_capture_recv_data[i].pause_output = &pause_output;
ftd3_libusb_capture_recv_data[i].internal_index = i;
ftd3_libusb_capture_recv_data[i].capture_data = capture_data;
ftd3_libusb_capture_recv_data[i].last_index = &last_index;

View File

@@ -54,14 +54,14 @@ uint64_t ftd3_get_video_in_size(CaptureData* capture_data) {
return sizeof(RGB83DSVideoInputData_3D);
}
static uint64_t ftd3_get_capture_size(CaptureStatus* capture_status) {
if(!get_3d_enabled(capture_status))
uint64_t ftd3_get_capture_size(bool is_3d_enabled) {
if(!is_3d_enabled)
return sizeof(FTD3_3DSCaptureReceived) & (~(EXTRA_DATA_BUFFER_FTD3XX_SIZE - 1));
return sizeof(FTD3_3DSCaptureReceived_3D) & (~(EXTRA_DATA_BUFFER_FTD3XX_SIZE - 1));
}
uint64_t ftd3_get_capture_size(CaptureData* capture_data) {
return ftd3_get_capture_size(&capture_data->status);
return ftd3_get_capture_size(get_3d_enabled(&capture_data->status));
}
static void preemptive_close_connection(CaptureData* capture_data) {
@@ -180,8 +180,6 @@ bool connect_ftd3(bool print_failed, CaptureData* capture_data, CaptureDevice* d
capture_error_print(print_failed, capture_data, "Second Create failed");
return false;
}
ftd3_device_device_handlers* handlers = (ftd3_device_device_handlers*)capture_data->handle;
if(!reset_3ds_state(print_failed, capture_data))
return false;
@@ -201,19 +199,47 @@ bool connect_ftd3(bool print_failed, CaptureData* capture_data, CaptureDevice* d
if(!read_3ds_config_3d(print_failed, capture_data, device))
return false;
CaptureStatus tmp_status;
tmp_status.device = *device;
tmp_status.connected = true;
tmp_status.requested_3d = capture_data->status.requested_3d;
if(!get_3d_enabled(&tmp_status)) {
if(!set_3ds_state(print_failed, capture_data, 0x42))
return false;
return true;
}
bool ftd3_capture_3d_setup(CaptureData* capture_data, bool first_pass, bool& stored_3d_status) {
CaptureStatus tmp_status;
tmp_status.device = capture_data->status.device;
tmp_status.connected = capture_data->status.connected;
tmp_status.requested_3d = capture_data->status.requested_3d;
if(first_pass)
stored_3d_status = true;
if((!first_pass) && ((stored_3d_status == tmp_status.requested_3d) || (!get_3d_enabled(&tmp_status, true)))) {
stored_3d_status = tmp_status.requested_3d;
return true;
}
ftd3_device_device_handlers* handlers = (ftd3_device_device_handlers*)capture_data->handle;
bool print_failed = true;
if(!first_pass) {
if(ftd3_is_error_compat(handlers, ftd3_abort_pipe_compat(handlers, BULK_IN))) {
capture_error_print(print_failed, capture_data, "Abort failed");
preemptive_close_connection(capture_data);
return false;
}
}
bool _3d_enabled_result = get_3d_enabled(&tmp_status);
bool update_state = stored_3d_status != _3d_enabled_result;
if(update_state) {
int state_to_set = 0x42;
if(_3d_enabled_result)
state_to_set = 0x43;
if(!set_3ds_state(print_failed, capture_data, state_to_set))
return false;
if(!set_3ds_state(print_failed, capture_data, 0x40))
return false;
}
if(ftd3_is_error_compat(handlers, ftd3_set_stream_pipe_compat(handlers, BULK_IN, ftd3_get_capture_size(&tmp_status)))) {
if(ftd3_is_error_compat(handlers, ftd3_set_stream_pipe_compat(handlers, BULK_IN, ftd3_get_capture_size(_3d_enabled_result)))) {
capture_error_print(print_failed, capture_data, "Stream failed");
preemptive_close_connection(capture_data);
return false;
@@ -226,16 +252,18 @@ bool connect_ftd3(bool print_failed, CaptureData* capture_data, CaptureDevice* d
return false;
}
if(ftd3_is_error_compat(handlers, ftd3_set_stream_pipe_compat(handlers, BULK_IN, ftd3_get_capture_size(&tmp_status)))) {
if(ftd3_is_error_compat(handlers, ftd3_set_stream_pipe_compat(handlers, BULK_IN, ftd3_get_capture_size(_3d_enabled_result)))) {
capture_error_print(print_failed, capture_data, "Stream failed");
preemptive_close_connection(capture_data);
return false;
}
}
stored_3d_status = tmp_status.requested_3d;
return true;
}
void ftd3_capture_main_loop(CaptureData* capture_data) {
bool could_have_3d = get_3d_enabled(&capture_data->status, true);
ftd3_main_loop_compat(capture_data, BULK_IN);
}

233
source/Menus/Main3DMenu.cpp Normal file
View File

@@ -0,0 +1,233 @@
#include "Main3DMenu.hpp"
#include "devicecapture.hpp"
#define NUM_TOTAL_MENU_OPTIONS (sizeof(pollable_options)/sizeof(pollable_options[0]))
struct Main3DMenuOptionInfo {
const std::string base_name;
const std::string false_name;
const bool is_selectable;
const bool is_inc;
const std::string dec_str;
const std::string inc_str;
const Main3DMenuOutAction inc_out_action;
const Main3DMenuOutAction out_action;
const bool selectable_joint;
const bool selectable_top;
const bool selectable_bottom;
};
static const Main3DMenuOptionInfo main_3d_menu_device_option = {
.base_name = "", .false_name = "", .is_selectable = false,
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = MAIN_3D_MENU_NO_ACTION,
.out_action = MAIN_3D_MENU_DEVICE_INFO,
.selectable_joint = true, .selectable_top = true, .selectable_bottom = true};
static const Main3DMenuOptionInfo main_3d_menu_usb_speed_option = {
.base_name = "", .false_name = "", .is_selectable = false,
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = MAIN_3D_MENU_NO_ACTION,
.out_action = MAIN_3D_MENU_USB_SPEED_INFO,
.selectable_joint = true, .selectable_top = true, .selectable_bottom = true};
static const Main3DMenuOptionInfo main_3d_menu_implemented_option = {
.base_name = "", .false_name = "", .is_selectable = false,
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = MAIN_3D_MENU_NO_ACTION,
.out_action = MAIN_3D_MENU_IMPLEMENTATION_INFO,
.selectable_joint = true, .selectable_top = true, .selectable_bottom = true};
static const Main3DMenuOptionInfo main_3d_menu_request_3d_option = {
.base_name = "Preference: 3D", .false_name = "Preference: 2D", .is_selectable = true,
.is_inc = true, .dec_str = "<", .inc_str = ">", .inc_out_action = MAIN_3D_MENU_REQUEST_3D_TOGGLE,
.out_action = MAIN_3D_MENU_REQUEST_3D_TOGGLE,
.selectable_joint = true, .selectable_top = true, .selectable_bottom = true};
static const Main3DMenuOptionInfo main_3d_menu_3d_interleaved_option = {
.base_name = "3D Style: Interleaved", .false_name = "3D Style: Separate", .is_selectable = true,
.is_inc = true, .dec_str = "<", .inc_str = ">", .inc_out_action = MAIN_3D_MENU_INTERLEAVED_TOGGLE,
.out_action = MAIN_3D_MENU_INTERLEAVED_TOGGLE,
.selectable_joint = true, .selectable_top = true, .selectable_bottom = true};
static const Main3DMenuOptionInfo main_3d_menu_squish_top_option = {
.base_name = "Stretch Top Screen", .false_name = "Squish Top Screen", .is_selectable = true,
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = MAIN_3D_MENU_NO_ACTION,
.out_action = MAIN_3D_MENU_SQUISH_TOP_TOGGLE,
.selectable_joint = true, .selectable_top = false, .selectable_bottom = false};
static const Main3DMenuOptionInfo main_3d_menu_squish_bottom_option = {
.base_name = "Stretch Bottom Screen", .false_name = "Squish Bottom Screen", .is_selectable = true,
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = MAIN_3D_MENU_NO_ACTION,
.out_action = MAIN_3D_MENU_SQUISH_BOTTOM_TOGGLE,
.selectable_joint = true, .selectable_top = false, .selectable_bottom = false};
static const Main3DMenuOptionInfo main_3d_menu_squish_mono_option = {
.base_name = "Stretch Screen", .false_name = "Squish Screen", .is_selectable = true,
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = MAIN_3D_MENU_NO_ACTION,
.out_action = MAIN_3D_MENU_SQUISH_TOP_TOGGLE,
.selectable_joint = false, .selectable_top = true, .selectable_bottom = false};
static const Main3DMenuOptionInfo main_3d_menu_second_screen_position_settings_option = {
.base_name = "3D Screen Placement", .false_name = "", .is_selectable = true,
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = MAIN_3D_MENU_NO_ACTION,
.out_action = MAIN_3D_MENU_SECOND_SCREEN_POSITION_SETTINGS,
.selectable_joint = true, .selectable_top = true, .selectable_bottom = false};
static const Main3DMenuOptionInfo* pollable_options[] = {
&main_3d_menu_device_option,
&main_3d_menu_usb_speed_option,
&main_3d_menu_implemented_option,
&main_3d_menu_request_3d_option,
&main_3d_menu_3d_interleaved_option,
&main_3d_menu_squish_top_option,
&main_3d_menu_squish_bottom_option,
&main_3d_menu_squish_mono_option,
&main_3d_menu_second_screen_position_settings_option,
};
Main3DMenu::Main3DMenu(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;
}
Main3DMenu::~Main3DMenu() {
delete []this->options_indexes;
}
void Main3DMenu::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 = "3D Settings";
this->show_back_x = true;
this->show_x = false;
this->show_title = true;
}
void Main3DMenu::insert_data(ScreenType stype) {
this->num_enabled_options = 0;
for(int i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) {
if((stype == ScreenType::BOTTOM) && (!pollable_options[i]->selectable_bottom))
continue;
if((stype == ScreenType::TOP) && (!pollable_options[i]->selectable_top))
continue;
if((stype == ScreenType::JOINT) && (!pollable_options[i]->selectable_joint))
continue;
this->options_indexes[this->num_enabled_options] = i;
this->num_enabled_options++;
}
this->prepare_options();
}
void Main3DMenu::reset_output_option() {
this->selected_index = Main3DMenuOutAction::MAIN_3D_MENU_NO_ACTION;
}
void Main3DMenu::set_output_option(int index, int action) {
if(index == BACK_X_OUTPUT_OPTION)
this->selected_index = MAIN_3D_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 Main3DMenu::get_num_options() {
return this->num_enabled_options;
}
std::string Main3DMenu::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;
if(action == FALSE_ACTION)
return pollable_options[this->options_indexes[index]]->false_name;
return pollable_options[this->options_indexes[index]]->base_name;
}
bool Main3DMenu::is_option_selectable(int index, int action) {
return pollable_options[this->options_indexes[index]]->is_selectable;
}
bool Main3DMenu::is_option_inc_dec(int index) {
return pollable_options[this->options_indexes[index]]->is_inc;
}
static std::string get_device_connected_firmware_info(bool is_device_connected, bool is_device_3ds, bool is_firmware_3d) {
if(!is_device_connected)
return "No device connected";
if(!is_device_3ds)
return "No 3DS connected";
if(!is_firmware_3d)
return "FW: No 3D";
return "FW: 3D";
}
static std::string get_usb_speed_3d_info(bool is_device_3ds, bool is_usb_speed_enough, int speed_device_connected) {
if(!is_device_3ds)
return "";
if(!is_usb_speed_enough)
return "USB " + std::to_string(speed_device_connected) + ": Slow";
return "USB " + std::to_string(speed_device_connected) + ": Ok";
}
static std::string get_implementation_info(bool is_device_3ds, bool is_implemented_3d) {
if(!is_device_3ds)
return "";
if(!is_implemented_3d)
return "3D not implemented";
return "3D implemented";
}
void Main3DMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info, DisplayData* display_data, CaptureStatus* status) {
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;
bool is_device_connected = status->connected;
bool is_device_3ds = is_device_connected && status->device.is_3ds;
int speed_device_connected = get_usb_speed_of_device(status);
bool is_usb_speed_enough = is_device_3ds && is_usb_speed_of_device_enough_3d(status);
bool is_implemented_3d = is_device_3ds && get_device_3d_implemented(status);
bool is_firmware_3d = is_device_3ds && get_device_can_do_3d(status);
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 MAIN_3D_MENU_DEVICE_INFO:
this->labels[index]->setText(get_device_connected_firmware_info(is_device_connected, is_device_3ds, is_firmware_3d));
break;
case MAIN_3D_MENU_USB_SPEED_INFO:
this->labels[index]->setText(get_usb_speed_3d_info(is_device_3ds, is_usb_speed_enough, speed_device_connected));
break;
case MAIN_3D_MENU_IMPLEMENTATION_INFO:
this->labels[index]->setText(get_implementation_info(is_device_3ds, is_implemented_3d));
break;
case MAIN_3D_MENU_REQUEST_3D_TOGGLE:
this->labels[index]->setText(this->setTextOptionBool(real_index, status->requested_3d));
break;
case MAIN_3D_MENU_INTERLEAVED_TOGGLE:
this->labels[index]->setText(this->setTextOptionBool(real_index, display_data->interleaved_3d));
break;
case MAIN_3D_MENU_SQUISH_TOP_TOGGLE:
this->labels[index]->setText(this->setTextOptionBool(real_index, info->squish_3d_top));
break;
case MAIN_3D_MENU_SQUISH_BOTTOM_TOGGLE:
this->labels[index]->setText(this->setTextOptionBool(real_index, info->squish_3d_bot));
break;
default:
break;
}
}
this->base_prepare(menu_scaling_factor, view_size_x, view_size_y);
}

View File

@@ -226,6 +226,7 @@ std::string OptionSelectionMenu::setTextOptionBool(int index, bool value) {
return this->get_string_option(index, DEFAULT_ACTION);
return this->get_string_option(index, FALSE_ACTION);
}
std::string OptionSelectionMenu::setTextOptionFloat(int index, float value, int num_decimals) {
std::string out = this->get_string_option(index, DEFAULT_ACTION) + ": " + get_float_str_decimals(value, num_decimals);
return out;

View File

@@ -9,43 +9,50 @@ struct RelativePositionMenuOptionInfo {
const int position_x, position_y, multiplier_y;
float text_factor_multiplier;
const BottomRelativePosition out_action;
const int divisor_x;
};
static const RelativePositionMenuOptionInfo above_option = {
.base_name = "Above", .is_selectable = true,
.position_x = 1, .position_y = 0, .multiplier_y = 1,
.text_factor_multiplier = 1.0,
.out_action = UNDER_TOP};
.out_action = UNDER_TOP,
.divisor_x = 3};
static const RelativePositionMenuOptionInfo left_option = {
.base_name = "Left", .is_selectable = true,
.position_x = 0, .position_y = 1, .multiplier_y = 1,
.text_factor_multiplier = 1.0,
.out_action = RIGHT_TOP};
.out_action = RIGHT_TOP,
.divisor_x = 3};
static const RelativePositionMenuOptionInfo right_option = {
.base_name = "Right", .is_selectable = true,
.position_x = 2, .position_y = 1, .multiplier_y = 1,
.text_factor_multiplier = 1.0,
.out_action = LEFT_TOP};
.out_action = LEFT_TOP,
.divisor_x = 3};
static const RelativePositionMenuOptionInfo below_option = {
.base_name = "Below", .is_selectable = true,
.position_x = 1, .position_y = 2, .multiplier_y = 1,
.text_factor_multiplier = 1.0,
.out_action = ABOVE_TOP};
.out_action = ABOVE_TOP,
.divisor_x = 3};
static const RelativePositionMenuOptionInfo desc_option = {
.base_name = "Top Screen", .is_selectable = false,
.position_x = 1, .position_y = 2, .multiplier_y = 2,
.text_factor_multiplier = 0.95,
.out_action = BOT_REL_POS_END};
.out_action = BOT_REL_POS_END,
.divisor_x = 3};
static const RelativePositionMenuOptionInfo desc2_option = {
.base_name = "Position", .is_selectable = false,
.position_x = 1, .position_y = 3, .multiplier_y = 2,
.text_factor_multiplier = 0.95,
.out_action = BOT_REL_POS_END};
.out_action = BOT_REL_POS_END,
.divisor_x = 3};
static const RelativePositionMenuOptionInfo* pollable_options[] = {
&above_option,
@@ -56,7 +63,21 @@ static const RelativePositionMenuOptionInfo* pollable_options[] = {
&desc2_option,
};
RelativePositionMenu::RelativePositionMenu() {
}
RelativePositionMenu::RelativePositionMenu(bool font_load_success, sf::Font &text_font) {
this->initialize(font_load_success, text_font);
}
RelativePositionMenu::~RelativePositionMenu() {
for(int i = 0; i < this->num_elements_displayed_per_screen; i++)
delete this->labels[i];
delete []this->labels;
delete []this->selectable_labels;
}
void RelativePositionMenu::initialize(bool font_load_success, sf::Font &text_font) {
this->class_setup();
this->after_class_setup_connected_values();
this->menu_rectangle.setFillColor(this->menu_color);
@@ -80,16 +101,10 @@ RelativePositionMenu::RelativePositionMenu(bool font_load_success, sf::Font &tex
this->selectable_labels[this->title_id] = false;
}
RelativePositionMenu::~RelativePositionMenu() {
for(int i = 0; i < this->num_elements_displayed_per_screen; i++)
delete this->labels[i];
delete []this->labels;
delete []this->selectable_labels;
}
void RelativePositionMenu::class_setup() {
this->num_options_per_screen = NUM_TOTAL_MENU_OPTIONS;
this->min_elements_text_scaling_factor = 4;
this->num_vertical_slices = 4;
this->width_factor_menu = 16;
this->width_divisor_menu = 9;
this->base_height_factor_menu = 12;
@@ -104,7 +119,6 @@ void RelativePositionMenu::after_class_setup_connected_values() {
this->num_title_back_x_elements = 2;
this->num_elements_per_screen = this->num_options_per_screen;
this->num_elements_displayed_per_screen = num_title_back_x_elements + num_elements_per_screen;
this->num_vertical_slices = 4;
this->title_back_x_start_id = 0;
this->elements_start_id = num_title_back_x_elements + title_back_x_start_id;
this->back_x_id = title_back_x_start_id + 1;
@@ -145,6 +159,22 @@ void RelativePositionMenu::set_default_cursor_position() {
}
}
bool RelativePositionMenu::is_option_left(int index) {
return pollable_options[index]->out_action == LEFT_TOP;
}
bool RelativePositionMenu::is_option_right(int index) {
return pollable_options[index]->out_action == RIGHT_TOP;
}
bool RelativePositionMenu::is_option_above(int index) {
return pollable_options[index]->out_action == ABOVE_TOP;
}
bool RelativePositionMenu::is_option_below(int index) {
return pollable_options[index]->out_action == UNDER_TOP;
}
void RelativePositionMenu::decrement_selected_option(bool is_simple) {
if(this->future_data.option_selected < 0) {
this->set_default_cursor_position();
@@ -152,7 +182,7 @@ void RelativePositionMenu::decrement_selected_option(bool is_simple) {
}
int elem_index = this->future_data.option_selected - this->elements_start_id;
if(!is_simple) {
if(this->is_option_element(this->future_data.option_selected) && ((pollable_options[elem_index]->out_action == LEFT_TOP) || (pollable_options[elem_index]->out_action == ABOVE_TOP)))
if(this->is_option_element(this->future_data.option_selected) && (this->is_option_left(elem_index) || this->is_option_above(elem_index)))
this->future_data.option_selected -= 1;
}
do {
@@ -169,7 +199,7 @@ void RelativePositionMenu::increment_selected_option(bool is_simple) {
}
int elem_index = this->future_data.option_selected - this->elements_start_id;
if(!is_simple) {
if(this->is_option_element(this->future_data.option_selected) && (pollable_options[elem_index]->out_action == RIGHT_TOP))
if(this->is_option_element(this->future_data.option_selected) && this->is_option_right(elem_index))
this->future_data.option_selected += 1;
}
do {
@@ -208,7 +238,7 @@ void RelativePositionMenu::prepare_options() {
this->labels[this->back_x_id]->setShowText(true);
this->labels[this->title_id]->setText(this->title);
this->labels[this->title_id]->setShowText(true);
for(int i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) {
for(int i = 0; i < this->num_options_per_screen; i++) {
int label_start_index = i + this->elements_start_id;
this->labels[label_start_index]->setText(this->get_string_option(i));
this->selectable_labels[label_start_index] = this->is_option_selectable(i);
@@ -254,12 +284,12 @@ void RelativePositionMenu::down_code(bool is_simple) {
void RelativePositionMenu::left_code() {
if(!this->can_execute_action())
return;
if(this->is_option_element(this->future_data.option_selected) && (pollable_options[this->future_data.option_selected - this->elements_start_id]->out_action == RIGHT_TOP))
if(this->is_option_element(this->future_data.option_selected) && this->is_option_right(this->future_data.option_selected - this->elements_start_id))
this->option_selection_handling();
else {
this->future_data.option_selected -= 1;
for(int i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) {
if(pollable_options[i]->out_action == RIGHT_TOP) {
for(int i = 0; i < this->num_options_per_screen; i++) {
if(this->is_option_right(i)) {
this->future_data.option_selected = i + this->elements_start_id;
break;
}
@@ -272,12 +302,12 @@ void RelativePositionMenu::right_code() {
if(!this->can_execute_action())
return;
int elem_index = this->future_data.option_selected - this->elements_start_id;
if(this->is_option_element(this->future_data.option_selected) && (pollable_options[this->future_data.option_selected - this->elements_start_id]->out_action == LEFT_TOP))
if(this->is_option_element(this->future_data.option_selected) && this->is_option_left(this->future_data.option_selected - this->elements_start_id))
this->option_selection_handling();
else {
this->future_data.option_selected -= 1;
for(int i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) {
if(pollable_options[i]->out_action == LEFT_TOP) {
for(int i = 0; i < this->num_options_per_screen; i++) {
if(this->is_option_left(i)) {
this->future_data.option_selected = i + this->elements_start_id;
break;
}
@@ -427,7 +457,7 @@ void RelativePositionMenu::prepare_text_slices(int x_multiplier, int x_divisor,
}
void RelativePositionMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y, BottomRelativePosition curr_bottom_pos) {
for(int i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) {
for(int i = 0; i < this->num_options_per_screen; i++) {
int index = i + this->elements_start_id;
switch(pollable_options[i]->out_action) {
case BOT_REL_POS_END:
@@ -444,6 +474,10 @@ void RelativePositionMenu::prepare(float menu_scaling_factor, int view_size_x, i
this->base_prepare(menu_scaling_factor, view_size_x, view_size_y);
}
void RelativePositionMenu::option_slice_prepare(int i, int index, int num_vertical_slices, float text_scaling_factor) {
this->prepare_text_slices(pollable_options[i]->position_x, pollable_options[i]->divisor_x, pollable_options[i]->position_y + (1 * pollable_options[i]->multiplier_y), num_vertical_slices * pollable_options[i]->multiplier_y, index, text_scaling_factor * pollable_options[i]->text_factor_multiplier);
}
void RelativePositionMenu::base_prepare(float menu_scaling_factor, int view_size_x, int view_size_y) {
const float base_height = (7 * BASE_PIXEL_FONT_HEIGHT * 11) / 9;
int max_width = (view_size_x * 9) / 10;
@@ -477,9 +511,9 @@ void RelativePositionMenu::base_prepare(float menu_scaling_factor, int view_size
int top_divisor = 6;
this->prepare_text_slices(0, 6, 0, this->num_vertical_slices, this->back_x_id, text_scaling_factor);
this->prepare_text_slices(0, 1, 0, this->num_vertical_slices, this->title_id, text_scaling_factor);
for(int i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) {
for(int i = 0; i < this->num_options_per_screen; i++) {
int index = i + this->elements_start_id;
this->prepare_text_slices(pollable_options[i]->position_x, 3, pollable_options[i]->position_y + (1 * pollable_options[i]->multiplier_y), this->num_vertical_slices * pollable_options[i]->multiplier_y, index, text_scaling_factor * pollable_options[i]->text_factor_multiplier);
this->option_slice_prepare(i, index, this->num_vertical_slices, text_scaling_factor);
}
this->loaded_data = this->future_data;
}

View File

@@ -0,0 +1,197 @@
#include "SecondScreen3DRelativePositionMenu.hpp"
#include "utils.hpp"
#define NUM_TOTAL_MENU_OPTIONS (sizeof(pollable_options)/sizeof(pollable_options[0]))
struct SecondScreen3DRelativePositionMenuOptionInfo {
const std::string base_name;
const std::string false_name;
const bool is_selectable;
const int position_x, position_y, multiplier_y;
float text_factor_multiplier;
const SecondScreen3DRelPosMenuOutAction out_action;
const SecondScreen3DRelativePosition out_position;
int divisor_x;
};
static const SecondScreen3DRelativePositionMenuOptionInfo above_option = {
.base_name = "Above", .false_name = "",
.is_selectable = true,
.position_x = 1, .position_y = 1, .multiplier_y = 1,
.text_factor_multiplier = 1.0,
.out_action = SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM,
.out_position = ABOVE_FIRST,
.divisor_x = 3};
static const SecondScreen3DRelativePositionMenuOptionInfo left_option = {
.base_name = "Left", .false_name = "",
.is_selectable = true,
.position_x = 0, .position_y = 2, .multiplier_y = 1,
.text_factor_multiplier = 1.0,
.out_action = SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM,
.out_position = LEFT_FIRST,
.divisor_x = 3};
static const SecondScreen3DRelativePositionMenuOptionInfo right_option = {
.base_name = "Right", .false_name = "",
.is_selectable = true,
.position_x = 2, .position_y = 2, .multiplier_y = 1,
.text_factor_multiplier = 1.0,
.out_action = SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM,
.out_position = RIGHT_FIRST,
.divisor_x = 3};
static const SecondScreen3DRelativePositionMenuOptionInfo below_option = {
.base_name = "Below", .false_name = "",
.is_selectable = true,
.position_x = 1, .position_y = 3, .multiplier_y = 1,
.text_factor_multiplier = 1.0,
.out_action = SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM,
.out_position = UNDER_FIRST,
.divisor_x = 3};
static const SecondScreen3DRelativePositionMenuOptionInfo desc_option = {
.base_name = "3D Screen", .false_name = "",
.is_selectable = false,
.position_x = 1, .position_y = 4, .multiplier_y = 2,
.text_factor_multiplier = 0.95,
.out_action = SECOND_SCREEN_3D_REL_POS_MENU_NO_ACTION,
.out_position = SECOND_SCREEN_3D_REL_POS_END,
.divisor_x = 3};
static const SecondScreen3DRelativePositionMenuOptionInfo desc2_option = {
.base_name = "Position", .false_name = "",
.is_selectable = false,
.position_x = 1, .position_y = 5, .multiplier_y = 2,
.text_factor_multiplier = 0.95,
.out_action = SECOND_SCREEN_3D_REL_POS_MENU_NO_ACTION,
.out_position = SECOND_SCREEN_3D_REL_POS_END,
.divisor_x = 3};
static const SecondScreen3DRelativePositionMenuOptionInfo match_option = {
.base_name = "Set Manual 3D Screen Pos.", .false_name = "Set Automatic 3D Screen Pos.",
.is_selectable = true,
.position_x = 0, .position_y = 0, .multiplier_y = 1,
.text_factor_multiplier = 1.0,
.out_action = SECOND_SCREEN_3D_REL_POS_MENU_TOGGLE_MATCH,
.out_position = SECOND_SCREEN_3D_REL_POS_END,
.divisor_x = 1};
static const SecondScreen3DRelativePositionMenuOptionInfo* pollable_options[] = {
&match_option,
&above_option,
&left_option,
&right_option,
&below_option,
&desc_option,
&desc2_option,
};
SecondScreen3DRelativePositionMenu::SecondScreen3DRelativePositionMenu(bool font_load_success, sf::Font &text_font) {
this->initialize(font_load_success, text_font);
}
SecondScreen3DRelativePositionMenu::~SecondScreen3DRelativePositionMenu() {
for(int i = 0; i < this->num_elements_displayed_per_screen; i++)
delete this->labels[i];
delete []this->labels;
delete []this->selectable_labels;
}
void SecondScreen3DRelativePositionMenu::class_setup() {
this->num_options_per_screen = NUM_TOTAL_MENU_OPTIONS;
this->min_elements_text_scaling_factor = 4;
this->num_vertical_slices = 5;
this->pos_y_subtractor = 0;
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 = "3D Screen Placement";
}
void SecondScreen3DRelativePositionMenu::insert_data(ScreenType stype) {
this->pos_y_subtractor = 0;
this->num_vertical_slices = 5;
this->prepare_options();
}
void SecondScreen3DRelativePositionMenu::reset_output_option() {
this->selected_index = SECOND_SCREEN_3D_REL_POS_MENU_NO_ACTION;
}
void SecondScreen3DRelativePositionMenu::set_output_option(int index) {
if(index == BACK_X_OUTPUT_OPTION)
this->selected_index = SECOND_SCREEN_3D_REL_POS_MENU_BACK;
else {
this->selected_index = pollable_options[index]->out_action;
this->selected_confirm_value = pollable_options[index]->out_position;
}
}
bool SecondScreen3DRelativePositionMenu::is_option_selectable(int index) {
return pollable_options[index]->is_selectable;
}
std::string SecondScreen3DRelativePositionMenu::get_string_option(int index) {
return pollable_options[index]->base_name;
}
std::string SecondScreen3DRelativePositionMenu::get_false_option(int index) {
return pollable_options[index]->false_name;
}
void SecondScreen3DRelativePositionMenu::option_slice_prepare(int i, int index, int num_vertical_slices, float text_scaling_factor) {
this->prepare_text_slices(pollable_options[i]->position_x, pollable_options[i]->divisor_x, pollable_options[i]->position_y - this->pos_y_subtractor + (1 * pollable_options[i]->multiplier_y), num_vertical_slices * pollable_options[i]->multiplier_y, index, text_scaling_factor * pollable_options[i]->text_factor_multiplier);
}
bool SecondScreen3DRelativePositionMenu::is_option_element(int option) {
return (option >= this->elements_start_id) && (option < (this->elements_start_id + this->num_elements_per_screen));
}
bool SecondScreen3DRelativePositionMenu::is_option_left(int index) {
return (pollable_options[index]->out_action == SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM) && (pollable_options[index]->out_position == RIGHT_FIRST);
}
bool SecondScreen3DRelativePositionMenu::is_option_right(int index) {
return (pollable_options[index]->out_action == SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM) && (pollable_options[index]->out_position == LEFT_FIRST);
}
bool SecondScreen3DRelativePositionMenu::is_option_above(int index) {
return (pollable_options[index]->out_action == SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM) && (pollable_options[index]->out_position == UNDER_FIRST);
}
bool SecondScreen3DRelativePositionMenu::is_option_below(int index) {
return (pollable_options[index]->out_action == SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM) && (pollable_options[index]->out_position == ABOVE_FIRST);
}
std::string SecondScreen3DRelativePositionMenu::setTextOptionBool(int index, bool value) {
if(value)
return this->get_string_option(index);
return this->get_false_option(index);
}
void SecondScreen3DRelativePositionMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y, ScreenInfo* info) {
SecondScreen3DRelativePosition curr_2nd_screen_3d_pos = info->second_screen_pos;
for(int i = 0; i < this->num_options_per_screen; i++) {
int index = i + this->elements_start_id;
switch(pollable_options[i]->out_action) {
case SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM:
if(pollable_options[i]->out_position == curr_2nd_screen_3d_pos)
this->labels[index]->setText("<" + this->get_string_option(i) + ">");
else
this->labels[index]->setText(this->get_string_option(i));
break;
case SECOND_SCREEN_3D_REL_POS_MENU_TOGGLE_MATCH:
this->labels[index]->setText(this->setTextOptionBool(i, info->match_bottom_pos_and_second_screen_pos));
break;
default:
break;
}
}
this->base_prepare(menu_scaling_factor, view_size_x, view_size_y);
}

View File

@@ -71,7 +71,7 @@ StatusMenu::~StatusMenu() {
void StatusMenu::class_setup() {
this->num_options_per_screen = 6;
this->min_elements_text_scaling_factor = num_options_per_screen + 2;
this->min_elements_text_scaling_factor = num_options_per_screen + 1;
this->width_factor_menu = 16;
this->width_divisor_menu = 9;
this->base_height_factor_menu = 12;

View File

@@ -195,12 +195,20 @@ static const VideoMenuOptionInfo separator_settings_option = {
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = VIDEO_MENU_NO_ACTION,
.out_action = VIDEO_MENU_SEPARATOR_SETTINGS};
static const VideoMenuOptionInfo main_menu_3d_settings_option = {
.base_name = "3D Settings", .false_name = "",
.active_fullscreen = true, .active_windowed_screen = true, .requires_titlebar_possible = false,
.active_joint_screen = true, .active_top_screen = true, .active_bottom_screen = true,
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = VIDEO_MENU_NO_ACTION,
.out_action = VIDEO_MENU_3D_SETTINGS};
static const VideoMenuOptionInfo* pollable_options[] = {
&crop_option,
&window_scaling_option,
&allow_fill_scaling_option,
&scaling_ratio_settings_option,
&menu_scaling_option,
&main_menu_3d_settings_option,
&bottom_screen_pos_option,
&separator_settings_option,
&vsync_option,

View File

@@ -32,7 +32,7 @@ struct shader_and_data {
static std::vector<shader_and_data> usable_shaders;
static bool is_size_valid(sf::Vector2f &size) {
static bool is_size_valid(sf::Vector2f size) {
return (size.x > 0.0) && (size.y > 0.0);
}
@@ -61,6 +61,7 @@ WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, Disp
FPSArrayInit(&this->poll_fps);
(void)this->in_tex.resize({MAX_IN_VIDEO_WIDTH * NUM_FRAMES_BLENDED, MAX_IN_VIDEO_HEIGHT});
this->m_in_rect_top.setTexture(&this->in_tex);
this->m_in_rect_top_right.setTexture(&this->in_tex);
this->m_in_rect_bot.setTexture(&this->in_tex);
this->display_data = display_data;
this->shared_data = shared_data;
@@ -80,6 +81,8 @@ WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, Disp
if(this->m_stype == ScreenType::BOTTOM)
this->win_title += "_bot";
this->last_connected_status = false;
this->last_enabled_3d = false;
this->last_interleaved_3d = false;
this->capture_status = capture_status;
if(this->display_data->mono_app_mode && this->m_stype == ScreenType::JOINT)
this->m_info.is_fullscreen = true;
@@ -133,6 +136,10 @@ void WindowScreen::build() {
this->m_out_rect_top.out_rect.setSize(top_screen_size);
this->m_out_rect_top.out_rect.setTexture(&this->m_out_rect_top.out_tex.getTexture());
(void)this->m_out_rect_top_right.out_tex.resize({(unsigned int)top_screen_size.x / 2, (unsigned int)top_screen_size.y});
this->m_out_rect_top_right.out_rect.setSize(top_screen_size);
this->m_out_rect_top_right.out_rect.setTexture(&this->m_out_rect_top_right.out_tex.getTexture());
(void)this->m_out_rect_bot.out_tex.resize({(unsigned int)bot_screen_size.x, (unsigned int)bot_screen_size.y});
this->m_out_rect_bot.out_rect.setSize(bot_screen_size);
this->m_out_rect_bot.out_rect.setTexture(&this->m_out_rect_bot.out_tex.getTexture());
@@ -225,6 +232,17 @@ void WindowScreen::draw(double frame_time, VideoOutputData* out_buf) {
}
if(!should_be_open)
this->m_info.is_fullscreen = false;
bool curr_enabled_3d = get_3d_enabled(this->capture_status);
if(this->last_enabled_3d != curr_enabled_3d) {
this->prepare_size_ratios(false, false);
this->future_operations.call_crop = true;
}
this->last_enabled_3d = curr_enabled_3d;
if(curr_enabled_3d && (this->last_interleaved_3d != this->display_data->interleaved_3d)) {
this->prepare_size_ratios(false, false);
this->future_operations.call_crop = true;
}
this->last_interleaved_3d = this->display_data->interleaved_3d;
this->loaded_menu = this->curr_menu;
loaded_operations = future_operations;
if(this->loaded_operations.call_create) {
@@ -367,6 +385,7 @@ void WindowScreen::print_notification_float(std::string base_text, float value,
void WindowScreen::prepare_screen_rendering() {
if(loaded_operations.call_blur) {
this->m_out_rect_top.out_tex.setSmooth(this->loaded_info.is_blurred);
this->m_out_rect_top_right.out_tex.setSmooth(this->loaded_info.is_blurred);
this->m_out_rect_bot.out_tex.setSmooth(this->loaded_info.is_blurred);
}
if(loaded_operations.call_crop) {
@@ -639,22 +658,22 @@ int WindowScreen::choose_shader(PossibleShaderTypes shader_type, bool is_top) {
return -1;
}
void WindowScreen::apply_shader_to_texture(out_rect_data &rect_data, PossibleShaderTypes shader_type, bool is_top) {
void WindowScreen::apply_shader_to_texture(sf::RectangleShape &rect_data, sf::RenderTexture &tex_data, PossibleShaderTypes shader_type, bool is_top) {
int chosen_shader = choose_shader(COLOR_PROCESSING_SHADER_TYPE, is_top);
if(chosen_shader < 0)
return;
sf::RectangleShape in_rect;
in_rect.setTexture(&rect_data.out_tex.getTexture());
const sf::IntRect texture_rect = rect_data.out_rect.getTextureRect();
in_rect.setTexture(&tex_data.getTexture());
const sf::IntRect texture_rect = rect_data.getTextureRect();
in_rect.setTextureRect(texture_rect);
in_rect.setSize({(float)texture_rect.size.x, (float)texture_rect.size.y});
in_rect.setPosition({(float)texture_rect.position.x, (float)texture_rect.position.y});
in_rect.setRotation(sf::degrees(0));
in_rect.setOrigin({0, 0});
rect_data.out_tex.draw(in_rect, &usable_shaders[chosen_shader].shader);
tex_data.draw(in_rect, &usable_shaders[chosen_shader].shader);
}
bool WindowScreen::apply_shaders_to_input(out_rect_data &rect_data, const sf::RectangleShape &final_in_rect, bool is_top) {
bool WindowScreen::apply_shaders_to_input(sf::RectangleShape &rect_data, sf::RenderTexture &tex_data, const sf::RectangleShape &final_in_rect, bool is_top) {
if(!sf::Shader::isAvailable())
return false;
@@ -667,13 +686,13 @@ bool WindowScreen::apply_shaders_to_input(out_rect_data &rect_data, const sf::Re
old_frame_pos_x = -1.0 / NUM_FRAMES_BLENDED;
sf::Glsl::Vec2 old_pos = {old_frame_pos_x, 0.0};
usable_shaders[chosen_shader].shader.setUniform("old_frame_offset", old_pos);
rect_data.out_tex.draw(final_in_rect, &usable_shaders[chosen_shader].shader);
tex_data.draw(final_in_rect, &usable_shaders[chosen_shader].shader);
this->apply_shader_to_texture(rect_data, COLOR_PROCESSING_SHADER_TYPE, is_top);
this->apply_shader_to_texture(rect_data, tex_data, COLOR_PROCESSING_SHADER_TYPE, is_top);
return true;
}
void WindowScreen::post_texture_conversion_processing(out_rect_data &rect_data, const sf::RectangleShape &in_rect, bool actually_draw, bool is_top, bool is_debug) {
void WindowScreen::post_texture_conversion_processing(sf::RectangleShape &rect_data, sf::RenderTexture &tex_data, const sf::RectangleShape &in_rect, bool actually_draw, bool is_top, bool is_debug) {
if((is_top && this->m_stype == ScreenType::BOTTOM) || ((!is_top) && this->m_stype == ScreenType::TOP))
return;
if(this->loaded_menu == CONNECT_MENU_TYPE)
@@ -681,24 +700,24 @@ void WindowScreen::post_texture_conversion_processing(out_rect_data &rect_data,
if(is_debug) {
if(is_top)
rect_data.out_tex.clear(sf::Color::Red);
tex_data.clear(sf::Color::Red);
else
rect_data.out_tex.clear(sf::Color::Blue);
tex_data.clear(sf::Color::Blue);
}
else {
rect_data.out_tex.clear();
tex_data.clear();
sf::RectangleShape final_in_rect = in_rect;
sf::IntRect text_coords_rect = final_in_rect.getTextureRect();
text_coords_rect.position.x += this->curr_frame_texture_pos * MAX_IN_VIDEO_WIDTH;
final_in_rect.setTextureRect(text_coords_rect);
if(this->capture_status->connected && actually_draw) {
bool use_default_shader = !(this->apply_shaders_to_input(rect_data, final_in_rect, is_top));
bool use_default_shader = !(this->apply_shaders_to_input(rect_data, tex_data, final_in_rect, is_top));
if(use_default_shader)
rect_data.out_tex.draw(final_in_rect);
tex_data.draw(final_in_rect);
//Place postprocessing effects here
}
}
rect_data.out_tex.display();
tex_data.display();
}
void WindowScreen::draw_rect_to_window(const sf::RectangleShape &out_rect, bool is_top) {
@@ -723,18 +742,81 @@ void WindowScreen::window_bg_processing() {
//Place BG processing here
}
sf::Vector2u WindowScreen::get_3d_size_multiplier(ScreenInfo* info) {
if((!get_3d_enabled(this->capture_status)) || (this->display_data->interleaved_3d))
return {1, 1};
SecondScreen3DRelativePosition second_screen_pos = get_second_screen_pos(info, this->m_stype);
if((second_screen_pos == UNDER_FIRST) || (second_screen_pos == ABOVE_FIRST))
return {1, 2};
return {2, 1};
}
sf::Vector2u WindowScreen::get_desk_mode_3d_multiplied(ScreenInfo* info) {
if((!get_3d_enabled(this->capture_status)) || (this->display_data->interleaved_3d) || (this->m_stype == ScreenType::BOTTOM) || (info->top_scaling == 0))
return curr_desk_mode.size;
return curr_desk_mode.size.componentWiseDiv(get_3d_size_multiplier(info));
}
sf::Vector2f WindowScreen::get_3d_offset_out_rect(ScreenInfo* info, bool is_second_screen) {
if((!get_3d_enabled(this->capture_status)) || (this->display_data->interleaved_3d))
return {0, 0};
float x_contribution = this->m_width_no_manip;
float y_contribution = this->m_height_no_manip;
if(info->is_fullscreen) {
sf::Vector2u curr_desk_mode_3d_size = get_desk_mode_3d_multiplied(info);
x_contribution = curr_desk_mode_3d_size.x;
y_contribution = curr_desk_mode_3d_size.y;
}
float offset_x_first_screen = 0;
float offset_y_first_screen = 0;
if((!info->is_fullscreen) && info->rounded_corners_fix) {
x_contribution -= LEFT_ROUNDED_PADDING;
y_contribution -= TOP_ROUNDED_PADDING;
}
SecondScreen3DRelativePosition second_screen_pos = get_second_screen_pos(info, this->m_stype);
if(second_screen_pos == ABOVE_FIRST)
offset_y_first_screen = y_contribution;
if(second_screen_pos == LEFT_FIRST)
offset_x_first_screen = x_contribution;
if(!is_second_screen)
return {offset_x_first_screen, offset_y_first_screen};
if((second_screen_pos == UNDER_FIRST) || (second_screen_pos == ABOVE_FIRST))
return {0, (-2 * offset_y_first_screen) + y_contribution};
return {(-2 * offset_x_first_screen) + x_contribution, 0};
}
void WindowScreen::display_data_to_window(bool actually_draw, bool is_debug) {
this->draw_lock->lock();
this->post_texture_conversion_processing(this->m_out_rect_top, this->m_in_rect_top, actually_draw, true, is_debug);
this->post_texture_conversion_processing(this->m_out_rect_bot, this->m_in_rect_bot, actually_draw, false, is_debug);
sf::RectangleShape out_rect_top = this->m_out_rect_top.out_rect;
sf::RectangleShape out_rect_top_right = this->m_out_rect_top_right.out_rect;
sf::RectangleShape out_rect_bot = this->m_out_rect_bot.out_rect;
sf::RectangleShape in_rect_top = this->m_in_rect_top;
sf::RectangleShape in_rect_top_right = this->m_in_rect_top_right;
sf::RectangleShape in_rect_bot = this->m_in_rect_bot;
this->post_texture_conversion_processing(out_rect_top, this->m_out_rect_top.out_tex, in_rect_top, actually_draw, true, is_debug);
this->post_texture_conversion_processing(out_rect_bot, this->m_out_rect_bot.out_tex, in_rect_bot, actually_draw, false, is_debug);
if(get_3d_enabled(this->capture_status) && (!this->display_data->interleaved_3d) && (this->m_stype != ScreenType::BOTTOM) && is_size_valid(out_rect_top.getSize())) {
out_rect_top_right.setTextureRect(out_rect_top.getTextureRect());
this->post_texture_conversion_processing(out_rect_top_right, this->m_out_rect_top_right.out_tex, in_rect_top_right, actually_draw, true, is_debug);
}
if(is_debug)
this->m_win.clear(sf::Color::Green);
else
this->m_win.clear();
this->window_bg_processing();
this->draw_rect_to_window(this->m_out_rect_top.out_rect, true);
this->draw_rect_to_window(this->m_out_rect_bot.out_rect, false);
this->draw_rect_to_window(out_rect_top, true);
this->draw_rect_to_window(out_rect_bot, false);
if(get_3d_enabled(this->capture_status) && (!this->display_data->interleaved_3d) && (this->m_stype != ScreenType::BOTTOM) && is_size_valid(out_rect_top.getSize())) {
sf::Vector2f offset_second_screen = get_3d_offset_out_rect(&this->loaded_info, true);
out_rect_top_right.setTextureRect(out_rect_top.getTextureRect());
out_rect_top_right.setSize(out_rect_top.getSize());
out_rect_top_right.setPosition(out_rect_top.getPosition() + offset_second_screen);
out_rect_top_right.setRotation(out_rect_top.getRotation());
this->draw_rect_to_window(out_rect_top_right, true);
out_rect_bot.setPosition(out_rect_bot.getPosition() + offset_second_screen);
this->draw_rect_to_window(out_rect_bot, false);
}
this->execute_menu_draws();
this->notification->draw(this->m_win);
this->m_win.display();
@@ -895,8 +977,9 @@ float WindowScreen::get_max_float_screen_multiplier(ResizingScreenData *own_scre
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);
sf::Vector2u curr_desk_mode_3d_size = get_desk_mode_3d_multiplied(&this->m_info);
int desk_height = curr_desk_mode_3d_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_3d_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) {
@@ -914,7 +997,7 @@ float WindowScreen::get_max_float_screen_multiplier(ResizingScreenData *own_scre
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);
get_par_size(own_width, own_height, 1.0, own_screen->par, own_screen->divide_3d_par);
if((own_screen->rotation / 10) % 2)
std::swap(own_width, own_height);
if((own_height == 0) || (own_width == 0))
@@ -933,7 +1016,7 @@ int WindowScreen::prepare_screen_ratio(ResizingScreenData *own_screen, int width
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, other_scaling, other_screen->par);
get_par_size(other_width, other_height, other_scaling, other_screen->par, other_screen->divide_3d_par);
return prepare_screen_ratio(own_screen, other_width, other_height, other_screen->rotation);
}
@@ -978,7 +1061,7 @@ bool WindowScreen::can_non_integerly_scale() {
void WindowScreen::rescale_nonint_subscreen(ResizingScreenData *main_screen_resize_data, ResizingScreenData *sub_screen_resize_data) {
int new_width = main_screen_resize_data->size.x;
int new_height = main_screen_resize_data->size.y;
get_par_size(new_width, new_height, *main_screen_resize_data->non_int_scaling, main_screen_resize_data->par);
get_par_size(new_width, new_height, *main_screen_resize_data->non_int_scaling, main_screen_resize_data->par, main_screen_resize_data->divide_3d_par);
*sub_screen_resize_data->non_int_scaling = this->get_max_float_screen_multiplier(sub_screen_resize_data, new_width, new_height, main_screen_resize_data->rotation);
if(!sub_screen_resize_data->use_non_int_scaling)
*sub_screen_resize_data->non_int_scaling = static_cast<int>(*sub_screen_resize_data->non_int_scaling);
@@ -1044,8 +1127,8 @@ void WindowScreen::non_integer_scale_screens(ResizingScreenData *top_screen_resi
int min_top_screen_height = top_screen_resize_data->size.y;
int min_bot_screen_width = bot_screen_resize_data->size.x;
int min_bot_screen_height = bot_screen_resize_data->size.y;
get_par_size(min_top_screen_width, min_top_screen_height, min_top_scaling, top_screen_resize_data->par);
get_par_size(min_bot_screen_width, min_bot_screen_height, min_bot_scaling, bot_screen_resize_data->par);
get_par_size(min_top_screen_width, min_top_screen_height, min_top_scaling, top_screen_resize_data->par, top_screen_resize_data->divide_3d_par);
get_par_size(min_bot_screen_width, min_bot_screen_height, min_bot_scaling, bot_screen_resize_data->par, bot_screen_resize_data->divide_3d_par);
ResizingScreenData *bigger_screen_resize_data = top_screen_resize_data;
ResizingScreenData *smaller_screen_resize_data = bot_screen_resize_data;
@@ -1065,8 +1148,9 @@ void WindowScreen::non_integer_scale_screens(ResizingScreenData *top_screen_resi
if((bot_screen_resize_data->rotation / 10) % 2)
std::swap(min_bot_screen_width, min_bot_screen_height);
int free_width = curr_desk_mode.size.x - (min_bot_screen_width + min_top_screen_width);
int free_height = curr_desk_mode.size.y - (min_bot_screen_height + min_top_screen_height);
sf::Vector2u curr_desk_mode_3d_size = get_desk_mode_3d_multiplied(&this->m_info);
int free_width = curr_desk_mode_3d_size.x - (min_bot_screen_width + min_top_screen_width);
int free_height = curr_desk_mode_3d_size.y - (min_bot_screen_height + min_top_screen_height);
switch(this->m_info.non_integer_mode) {
case SMALLER_PRIORITY:
@@ -1093,10 +1177,10 @@ void WindowScreen::merge_screens_data(ResizingScreenData* top_screen_resize_data
// 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);
get_par_size(top_width, top_height, 1.0, top_screen_resize_data->par, top_screen_resize_data->divide_3d_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);
get_par_size(bot_width, bot_height, 1.0, bot_screen_resize_data->par, bot_screen_resize_data->divide_3d_par);
if((top_screen_resize_data->rotation / 10) % 2)
std::swap(top_width, top_height);
if((bot_screen_resize_data->rotation / 10) % 2)
@@ -1132,7 +1216,7 @@ bool WindowScreen::prepare_screens_same_scaling_factor(ResizingScreenData* top_s
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};
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, .divide_3d_par = false};
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, true);
scaling_merged = non_int_scaling_merged;
@@ -1147,6 +1231,14 @@ bool WindowScreen::prepare_screens_same_scaling_factor(ResizingScreenData* top_s
return true;
}
bool WindowScreen::get_divide_3d_par(bool is_top, ScreenInfo* info) {
if(!get_3d_enabled(this->capture_status))
return false;
if(!is_top)
return info->squish_3d_bot;
return info->squish_3d_top;
}
void WindowScreen::prepare_size_ratios(bool top_increase, bool bot_increase, bool cycle) {
if(!this->m_info.is_fullscreen)
return;
@@ -1172,8 +1264,8 @@ void WindowScreen::prepare_size_ratios(bool top_increase, bool bot_increase, boo
this->m_info.top_par = 0;
if((this->m_info.bot_par >= this->possible_pars.size()) || (this->m_info.bot_par < 0))
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]};
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], .divide_3d_par = get_divide_3d_par(true, &this->m_info)};
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], .divide_3d_par = get_divide_3d_par(false, &this->m_info)};
bool processed = false;
if(this->m_stype == ScreenType::JOINT && this->m_info.force_same_scaling)
@@ -1208,7 +1300,8 @@ int WindowScreen::get_fullscreen_offset_x(int top_width, int top_height, int bot
default:
return 0;
}
return (curr_desk_mode.size.x - offset_contribute) * this->loaded_info.total_offset_x;
sf::Vector2u curr_desk_mode_3d_size = get_desk_mode_3d_multiplied(&this->loaded_info);
return (curr_desk_mode_3d_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 separator_contribute) {
@@ -1230,7 +1323,8 @@ int WindowScreen::get_fullscreen_offset_y(int top_width, int top_height, int bot
default:
return 0;
}
return (curr_desk_mode.size.y - offset_contribute) * this->loaded_info.total_offset_y;
sf::Vector2u curr_desk_mode_3d_size = get_desk_mode_3d_multiplied(&this->loaded_info);
return (curr_desk_mode_3d_size.y - offset_contribute) * this->loaded_info.total_offset_y;
}
void WindowScreen::resize_window_and_out_rects(bool do_work) {
@@ -1259,8 +1353,8 @@ void WindowScreen::resize_window_and_out_rects(bool do_work) {
this->loaded_info.top_par = 0;
if((this->loaded_info.bot_par >= this->possible_pars.size()) || (this->loaded_info.bot_par < 0))
this->loaded_info.bot_par = 0;
get_par_size(top_width, top_height, top_scaling, this->possible_pars[this->loaded_info.top_par]);
get_par_size(bot_width, bot_height, bot_scaling, this->possible_pars[this->loaded_info.bot_par]);
get_par_size(top_width, top_height, top_scaling, this->possible_pars[this->loaded_info.top_par], get_divide_3d_par(true, &this->loaded_info));
get_par_size(bot_width, bot_height, bot_scaling, this->possible_pars[this->loaded_info.bot_par], get_divide_3d_par(false, &this->loaded_info));
if((!this->loaded_info.is_fullscreen) && this->loaded_info.rounded_corners_fix) {
offset_y = TOP_ROUNDED_PADDING;
@@ -1272,8 +1366,9 @@ void WindowScreen::resize_window_and_out_rects(bool do_work) {
if(this->loaded_info.is_fullscreen) {
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;
sf::Vector2u curr_desk_mode_3d_size = get_desk_mode_3d_multiplied(&this->loaded_info);
max_x = curr_desk_mode_3d_size.x;
max_y = curr_desk_mode_3d_size.y;
}
sf::Vector2f new_top_screen_size = {(float)top_width, (float)top_height};
sf::Vector2f new_bot_screen_size = {(float)bot_width, (float)bot_height};
@@ -1284,6 +1379,20 @@ void WindowScreen::resize_window_and_out_rects(bool do_work) {
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, separator_size_x, separator_size_y, do_work);
this->m_width_no_manip = this->m_width;
this->m_height_no_manip = this->m_height;
if(get_3d_enabled(this->capture_status) && (!this->display_data->interleaved_3d) && (this->m_stype != ScreenType::BOTTOM) && is_size_valid(this->m_out_rect_top.out_rect.getSize())) {
sf::Vector2f offset_first_screen = get_3d_offset_out_rect(&this->loaded_info, false);
this->m_out_rect_top.out_rect.setPosition(this->m_out_rect_top.out_rect.getPosition() + offset_first_screen);
this->m_out_rect_bot.out_rect.setPosition(this->m_out_rect_bot.out_rect.getPosition() + offset_first_screen);
if(!this->loaded_info.is_fullscreen) {
sf::Vector2f offset_to_apply = offset_first_screen;
if((offset_first_screen.x <= 0) && (offset_first_screen.y <= 0))
offset_to_apply = get_3d_offset_out_rect(&this->loaded_info, true);
this->m_width += offset_to_apply.x;
this->m_height += offset_to_apply.y;
}
}
if((!this->loaded_info.is_fullscreen) && this->loaded_info.rounded_corners_fix) {
this->m_height += BOTTOM_ROUNDED_PADDING;
this->m_width += RIGHT_ROUNDED_PADDING;
@@ -1396,6 +1505,8 @@ sf::Vector2f WindowScreen::getShownScreenSize(bool is_top, ScreenInfo* info) {
*crop_kind = 0;
int width = (*crops)[*crop_kind]->top_width;
int height = (*crops)[*crop_kind]->top_height;
if(get_3d_enabled(this->capture_status) && this->display_data->interleaved_3d)
width *= 2;
if(!is_top) {
width = (*crops)[*crop_kind]->bot_width;
height = (*crops)[*crop_kind]->bot_height;
@@ -1410,8 +1521,21 @@ void WindowScreen::crop() {
sf::Vector2f top_screen_size = getShownScreenSize(true, &this->loaded_info);
sf::Vector2f bot_screen_size = getShownScreenSize(false, &this->loaded_info);
this->resize_in_rect(this->m_in_rect_top, this->capture_status->device.top_screen_x + (*crops)[*crop_value]->top_x, this->capture_status->device.top_screen_y + (*crops)[*crop_value]->top_y, top_screen_size.x, top_screen_size.y);
this->resize_in_rect(this->m_in_rect_bot, this->capture_status->device.bot_screen_x + (*crops)[*crop_value]->bot_x, this->capture_status->device.bot_screen_y + (*crops)[*crop_value]->bot_y, bot_screen_size.x, bot_screen_size.y);
if(get_3d_enabled(this->capture_status) && (!this->display_data->interleaved_3d)) {
int left_top_screen_x = this->capture_status->device.top_screen_x;
int left_top_screen_y = this->capture_status->device.top_screen_y;
int right_top_screen_x = this->capture_status->device.second_top_screen_x;
int right_top_screen_y = this->capture_status->device.second_top_screen_y;
if(!this->capture_status->device.is_second_top_screen_right) {
std::swap(left_top_screen_x, right_top_screen_x);
std::swap(left_top_screen_y, right_top_screen_y);
}
this->resize_in_rect(this->m_in_rect_top, left_top_screen_x + (*crops)[*crop_value]->top_x, left_top_screen_y + (*crops)[*crop_value]->top_y, top_screen_size.x, top_screen_size.y);
this->resize_in_rect(this->m_in_rect_top_right, right_top_screen_x + (*crops)[*crop_value]->top_x, right_top_screen_y + (*crops)[*crop_value]->top_y, top_screen_size.x, top_screen_size.y);
}
else
this->resize_in_rect(this->m_in_rect_top, this->capture_status->device.top_screen_x + (*crops)[*crop_value]->top_x, this->capture_status->device.top_screen_y + (*crops)[*crop_value]->top_y, top_screen_size.x, top_screen_size.y);
this->loaded_operations.call_screen_settings_update = true;
}

View File

@@ -2,6 +2,7 @@
#include "frontend.hpp"
#include "SFML/Audio/PlaybackDevice.hpp"
#include "devicecapture.hpp"
#define FPS_WINDOW_SIZE 64
@@ -120,6 +121,8 @@ void WindowScreen::init_menus() {
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);
this->color_correction_menu = new ColorCorrectionMenu(this->font_load_success, this->text_font);
this->main_3d_menu = new Main3DMenu(this->font_load_success, this->text_font);
this->second_screen_3d_relpos_menu = new SecondScreen3DRelativePositionMenu(this->font_load_success, this->text_font);
}
void WindowScreen::destroy_menus() {
@@ -147,6 +150,8 @@ void WindowScreen::destroy_menus() {
delete this->audio_device_menu;
delete this->separator_menu;
delete this->color_correction_menu;
delete this->main_3d_menu;
delete this->second_screen_3d_relpos_menu;
}
void WindowScreen::set_close(int ret_val) {
@@ -317,6 +322,35 @@ void WindowScreen::color_correction_value_change(int new_color_correction_value)
this->print_notification(setting_name + this->possible_color_profiles[color_correction_index]->name);
}
void WindowScreen::request_3d_change() {
bool updated = update_3d_enabled(this->capture_status);
if(updated) {
this->prepare_size_ratios(false, false);
this->future_operations.call_crop = true;
}
}
void WindowScreen::interleaved_3d_change() {
this->display_data->interleaved_3d = !this->display_data->interleaved_3d;
bool updated = get_3d_enabled(this->capture_status);
if(updated) {
this->prepare_size_ratios(false, false);
this->future_operations.call_crop = true;
}
}
void WindowScreen::squish_3d_change(bool is_top) {
if(is_top)
this->m_info.squish_3d_top = !this->m_info.squish_3d_top;
else
this->m_info.squish_3d_bot = !this->m_info.squish_3d_bot;
bool updated = get_3d_enabled(this->capture_status);
if(updated) {
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
}
}
void WindowScreen::offset_change(float &value, float change) {
if(change >= 1.0)
return;
@@ -422,8 +456,33 @@ void WindowScreen::input_toggle_change(bool &target) {
void WindowScreen::bottom_pos_change(int new_bottom_pos) {
BottomRelativePosition cast_new_bottom_pos = static_cast<BottomRelativePosition>(new_bottom_pos % BottomRelativePosition::BOT_REL_POS_END);
if(cast_new_bottom_pos != this->m_info.bottom_pos) {
this->m_info.bottom_pos = cast_new_bottom_pos;
bool updated = cast_new_bottom_pos != this->m_info.bottom_pos;
this->m_info.bottom_pos = cast_new_bottom_pos;
if(updated) {
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
}
}
void WindowScreen::second_screen_3d_pos_change(int new_second_screen_3d_pos) {
SecondScreen3DRelativePosition cast_new_pos = static_cast<SecondScreen3DRelativePosition>(new_second_screen_3d_pos % SecondScreen3DRelativePosition::SECOND_SCREEN_3D_REL_POS_END);
SecondScreen3DRelativePosition prev_pos = get_second_screen_pos(&this->m_info, this->m_stype);
this->m_info.second_screen_pos = cast_new_pos;
SecondScreen3DRelativePosition curr_pos = get_second_screen_pos(&this->m_info, this->m_stype);
bool updated = get_3d_enabled(this->capture_status) && (prev_pos != curr_pos);
if(updated) {
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
}
}
void WindowScreen::second_screen_3d_match_bottom_pos_change() {
SecondScreen3DRelativePosition prev_pos = get_second_screen_pos(&this->m_info, this->m_stype);
this->m_info.match_bottom_pos_and_second_screen_pos = !this->m_info.match_bottom_pos_and_second_screen_pos;
SecondScreen3DRelativePosition curr_pos = get_second_screen_pos(&this->m_info, this->m_stype);
bool updated = get_3d_enabled(this->capture_status) && (prev_pos != curr_pos);
if(updated) {
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
}
@@ -1145,6 +1204,30 @@ void WindowScreen::setup_color_correction_menu(bool reset_data) {
}
}
void WindowScreen::setup_main_3d_menu(bool reset_data) {
if(!this->can_setup_menu())
return;
if(this->curr_menu != MAIN_3D_MENU_TYPE) {
this->curr_menu = MAIN_3D_MENU_TYPE;
if(reset_data)
this->main_3d_menu->reset_data();
this->main_3d_menu->insert_data(this->m_stype);
this->last_menu_change_time = std::chrono::high_resolution_clock::now();
}
}
void WindowScreen::setup_second_screen_3d_relpos_menu(bool reset_data) {
if(!this->can_setup_menu())
return;
if(this->curr_menu != SECOND_SCREEN_RELATIVE_POS_MENU_TYPE) {
this->curr_menu = SECOND_SCREEN_RELATIVE_POS_MENU_TYPE;
if(reset_data)
this->second_screen_3d_relpos_menu->reset_data();
this->second_screen_3d_relpos_menu->insert_data(this->m_stype);
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;
@@ -1692,6 +1775,9 @@ void WindowScreen::poll(bool do_everything) {
case VIDEO_MENU_SEPARATOR_SETTINGS:
this->setup_separator_menu();
break;
case VIDEO_MENU_3D_SETTINGS:
this->setup_main_3d_menu();
break;
default:
break;
}
@@ -2229,6 +2315,60 @@ void WindowScreen::poll(bool do_everything) {
continue;
}
break;
case MAIN_3D_MENU_TYPE:
if(this->main_3d_menu->poll(event_data)) {
switch(this->main_3d_menu->selected_index) {
case MAIN_3D_MENU_BACK:
this->setup_video_menu(false);
done = true;
break;
case MAIN_3D_MENU_NO_ACTION:
break;
case MAIN_3D_MENU_REQUEST_3D_TOGGLE:
this->request_3d_change();
break;
case MAIN_3D_MENU_INTERLEAVED_TOGGLE:
this->interleaved_3d_change();
break;
case MAIN_3D_MENU_SQUISH_TOP_TOGGLE:
this->squish_3d_change(true);
break;
case MAIN_3D_MENU_SQUISH_BOTTOM_TOGGLE:
this->squish_3d_change(false);
break;
case MAIN_3D_MENU_SECOND_SCREEN_POSITION_SETTINGS:
this->setup_second_screen_3d_relpos_menu();
done = true;
break;
default:
break;
}
this->main_3d_menu->reset_output_option();
continue;
}
break;
case SECOND_SCREEN_RELATIVE_POS_MENU_TYPE:
if(this->second_screen_3d_relpos_menu->poll(event_data)) {
switch(this->second_screen_3d_relpos_menu->selected_index) {
case SECOND_SCREEN_3D_REL_POS_MENU_BACK:
this->setup_main_3d_menu(false);
done = true;
break;
case SECOND_SCREEN_3D_REL_POS_MENU_NO_ACTION:
break;
case SECOND_SCREEN_3D_REL_POS_MENU_CONFIRM:
this->second_screen_3d_pos_change(this->second_screen_3d_relpos_menu->selected_confirm_value);
break;
case SECOND_SCREEN_3D_REL_POS_MENU_TOGGLE_MATCH:
this->second_screen_3d_match_bottom_pos_change();
break;
default:
break;
}
this->second_screen_3d_relpos_menu->reset_output_option();
continue;
}
break;
default:
break;
}
@@ -2511,6 +2651,12 @@ void WindowScreen::prepare_menu_draws(int view_size_x, int view_size_y) {
case COLOR_CORRECTION_MENU_TYPE:
this->color_correction_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, this->loaded_info.top_color_correction);
break;
case MAIN_3D_MENU_TYPE:
this->main_3d_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, &this->loaded_info, this->display_data, this->capture_status);
break;
case SECOND_SCREEN_RELATIVE_POS_MENU_TYPE:
this->second_screen_3d_relpos_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, &this->loaded_info);
break;
default:
break;
}
@@ -2596,6 +2742,12 @@ void WindowScreen::execute_menu_draws() {
case COLOR_CORRECTION_MENU_TYPE:
this->color_correction_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win);
break;
case MAIN_3D_MENU_TYPE:
this->main_3d_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win);
break;
case SECOND_SCREEN_RELATIVE_POS_MENU_TYPE:
this->second_screen_3d_relpos_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win);
break;
default:
break;
}

View File

@@ -615,6 +615,8 @@ static int mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data,
num_allowed_blanks--;
else
blank_out = true;
if(capture_data->status.cooldown_curr_in || (!capture_data->status.connected))
blank_out = true;
no_data_consecutive++;
}
}

View File

@@ -69,38 +69,40 @@ static void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_
}
}
else {
size_t last_line_index = ((IN_VIDEO_SIZE_3DS_3D - IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D) / (IN_VIDEO_WIDTH_3DS_3D * 3)) - 1;
size_t top_left_last_line_out_pos = 0;
size_t top_right_last_line_out_pos = 0;
if(!interleaved_3d) {
// Optimize for speed
for(int i = 0; i < (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / (IN_VIDEO_WIDTH_3DS_3D * 2)); i++) {
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, ((i * 2) + 0) * IN_VIDEO_WIDTH_3DS_3D, BOT_SIZE_3DS + TOP_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS_3D));
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, ((i * 2) + 1) * IN_VIDEO_WIDTH_3DS_3D, BOT_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS_3D));
}
for(int i = 0; i < ((IN_VIDEO_SIZE_3DS_3D - IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D) / (IN_VIDEO_WIDTH_3DS_3D * 3)) - 1; i++) {
for(int i = 0; i < last_line_index; i++) {
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 0) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, BOT_SIZE_3DS + TOP_SIZE_3DS + (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (i * IN_VIDEO_WIDTH_3DS_3D));
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 1) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, BOT_SIZE_3DS + (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (i * IN_VIDEO_WIDTH_3DS_3D));
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 2) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, i * IN_VIDEO_WIDTH_3DS_3D);
}
// For some weird reason, the last one is the opposite for bottom and
// second top screen
int i = ((IN_VIDEO_SIZE_3DS_3D - IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D) / (IN_VIDEO_WIDTH_3DS_3D * 3)) - 1;
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 0) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, BOT_SIZE_3DS + TOP_SIZE_3DS + (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (i * IN_VIDEO_WIDTH_3DS_3D));
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 2) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, BOT_SIZE_3DS + (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (i * IN_VIDEO_WIDTH_3DS_3D));
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 1) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, i * IN_VIDEO_WIDTH_3DS_3D);
top_left_last_line_out_pos = BOT_SIZE_3DS + TOP_SIZE_3DS + (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (last_line_index * IN_VIDEO_WIDTH_3DS_3D);
top_right_last_line_out_pos = BOT_SIZE_3DS + (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (last_line_index * IN_VIDEO_WIDTH_3DS_3D);
}
else {
// Optimize for speed
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, 0, BOT_SIZE_3DS);
for(int i = 0; i < ((IN_VIDEO_SIZE_3DS_3D - IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D) / (IN_VIDEO_WIDTH_3DS_3D * 3)) - 1; i++) {
for(int i = 0; i < last_line_index; i++) {
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D * 2, (((i * 3) + 0) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, BOT_SIZE_3DS + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D + (i * IN_VIDEO_WIDTH_3DS_3D * 2));
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 2) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, i * IN_VIDEO_WIDTH_3DS_3D);
}
// For some weird reason, the last one is the opposite for bottom and
// second top screen
int i = ((IN_VIDEO_SIZE_3DS_3D - IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D) / (IN_VIDEO_WIDTH_3DS_3D * 3)) - 1;
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 0) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, BOT_SIZE_3DS + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D + (i * IN_VIDEO_WIDTH_3DS_3D * 2));
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 2) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, BOT_SIZE_3DS + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D + (i * IN_VIDEO_WIDTH_3DS_3D * 2) + IN_VIDEO_WIDTH_3DS_3D);
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 1) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, i * IN_VIDEO_WIDTH_3DS_3D);
top_left_last_line_out_pos = BOT_SIZE_3DS + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D + (last_line_index * IN_VIDEO_WIDTH_3DS_3D * 2);
top_right_last_line_out_pos = BOT_SIZE_3DS + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D + (last_line_index * IN_VIDEO_WIDTH_3DS_3D * 2) + IN_VIDEO_WIDTH_3DS_3D;
}
// For some weird reason, the last one is the opposite for bottom and
// second top screen
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((last_line_index * 3) + 0) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, top_left_last_line_out_pos);
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((last_line_index * 3) + 2) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, top_right_last_line_out_pos);
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((last_line_index * 3) + 1) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, last_line_index * IN_VIDEO_WIDTH_3DS_3D);
}
}

View File

@@ -57,6 +57,10 @@ void capture_error_print(bool print_failed, CaptureData* capture_data, std::stri
}
void capture_error_print(bool print_failed, CaptureData* capture_data, std::string graphical_string, std::string detailed_string) {
if(capture_data->status.connected) {
capture_data->status.close_success = false;
capture_data->status.connected = false;
}
if(print_failed) {
capture_data->status.graphical_error_text = graphical_string;
capture_data->status.detailed_error_text = detailed_string;
@@ -70,12 +74,13 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten
capture_data->status.close_success = false;
return false;
}
if(!capture_data->status.close_success) {
capture_error_print(print_failed, capture_data, "Previous device still closing...");
return false;
}
capture_data->status.cooldown_curr_in = FIX_PARTIAL_FIRST_FRAME_NUM;
// Device Listing
std::vector<CaptureDevice> devices_list;
std::vector<no_access_recap_data> no_access_list;
@@ -267,6 +272,16 @@ int get_usb_speed_of_device(CaptureStatus* capture_status) {
return capture_status->device.usb_speed >> 8;
}
bool is_usb_speed_of_device_enough_3d(CaptureStatus* capture_status) {
switch(capture_status->device.cc_type) {
default:
if(get_usb_speed_of_device(capture_status) < 3)
return false;
break;
}
return true;
}
bool get_device_can_do_3d(CaptureStatus* capture_status) {
if(!capture_status->connected)
return false;
@@ -286,8 +301,8 @@ bool get_device_3d_implemented(CaptureStatus* capture_status) {
}
}
bool get_3d_enabled(CaptureStatus* capture_status) {
if(!capture_status->requested_3d)
bool get_3d_enabled(CaptureStatus* capture_status, bool skip_requested_3d_check) {
if((!skip_requested_3d_check) && (!capture_status->requested_3d))
return false;
if(!capture_status->connected)
return false;
@@ -295,15 +310,19 @@ bool get_3d_enabled(CaptureStatus* capture_status) {
return false;
if(!get_device_3d_implemented(capture_status))
return false;
switch(capture_status->device.cc_type) {
default:
if(get_usb_speed_of_device(capture_status) < 3)
return false;
break;
}
if(!is_usb_speed_of_device_enough_3d(capture_status))
return false;
return true;
}
bool update_3d_enabled(CaptureStatus* capture_status) {
bool would_3d_be_enabled = get_3d_enabled(capture_status, true);
if(would_3d_be_enabled && (capture_status->cooldown_curr_in < FIX_PARTIAL_FIRST_FRAME_NUM))
capture_status->cooldown_curr_in = FIX_PARTIAL_FIRST_FRAME_NUM;
capture_status->requested_3d = !capture_status->requested_3d;
return would_3d_be_enabled;
}
void capture_init() {
#ifdef USE_DS_3DS_USB
usb_ds_3ds_init();

View File

@@ -573,6 +573,7 @@ void reset_screen_info(ScreenInfo &info) {
info.scaling = DEFAULT_WINDOW_SCALING_VALUE;
info.is_fullscreen = false;
info.bottom_pos = UNDER_TOP;
info.second_screen_pos = RIGHT_FIRST;
info.subscreen_offset = 0.5;
info.subscreen_attached_offset = 0.0;
info.total_offset_x = 0.5;
@@ -616,6 +617,9 @@ void reset_screen_info(ScreenInfo &info) {
info.separator_pixel_size = DEFAULT_SEP_SIZE;
info.separator_windowed_multiplier = SEP_FOLLOW_SCALING_MULTIPLIER;
info.separator_fullscreen_multiplier = DEFAULT_WINDOW_SCALING_VALUE;
info.squish_3d_top = false;
info.squish_3d_bot = false;
info.match_bottom_pos_and_second_screen_pos = false;
}
void override_set_data_to_screen_info(override_win_data &override_win, ScreenInfo &info) {
@@ -854,7 +858,23 @@ bool load_screen_info(std::string key, std::string value, std::string base, Scre
return true;
}
if(key == (base + "window_enabled")) {
info.window_enabled = frame_blending_sanitization(std::stoi(value));
info.window_enabled = std::stoi(value);
return true;
}
if(key == (base + "second_screen_pos")) {
info.second_screen_pos = static_cast<SecondScreen3DRelativePosition>(std::stoi(value) % SecondScreen3DRelativePosition::SECOND_SCREEN_3D_REL_POS_END);
return true;
}
if(key == (base + "squish_3d_top")) {
info.squish_3d_top = std::stoi(value);
return true;
}
if(key == (base + "squish_3d_bot")) {
info.squish_3d_bot = std::stoi(value);
return true;
}
if(key == (base + "match_bottom_pos_and_second_screen_pos")) {
info.match_bottom_pos_and_second_screen_pos = std::stoi(value);
return true;
}
return false;
@@ -904,6 +924,10 @@ std::string save_screen_info(std::string base, const ScreenInfo &info) {
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";
out += base + "second_screen_pos=" + std::to_string(info.second_screen_pos) + "\n";
out += base + "squish_3d_top=" + std::to_string(info.squish_3d_top) + "\n";
out += base + "squish_3d_bot=" + std::to_string(info.squish_3d_bot) + "\n";
out += base + "match_bottom_pos_and_second_screen_pos=" + std::to_string(info.match_bottom_pos_and_second_screen_pos) + "\n";
return out;
}
@@ -923,9 +947,12 @@ 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) {
void get_par_size(int &width, int &height, float multiplier_factor, const PARData *correction_factor, bool divide_3d_par) {
width *= multiplier_factor;
height *= multiplier_factor;
float correction_factor_3d = 1.0;
if(divide_3d_par)
correction_factor_3d = 2.0;
float correction_factor_divisor = correction_factor->width_multiplier;
if(correction_factor->is_width_main)
correction_factor_divisor = correction_factor->width_divisor;
@@ -933,37 +960,64 @@ void get_par_size(int &width, int &height, float multiplier_factor, const PARDat
if(correction_factor->is_fit) {
if(correction_factor->is_width_main)
width = ((height * correction_factor->width_multiplier) + correction_factor_approx_contribute) / correction_factor_divisor;
else
else {
width /= correction_factor_3d;
height = ((width * correction_factor->width_divisor) + correction_factor_approx_contribute) / correction_factor_divisor;
}
}
else {
if(correction_factor->is_width_main)
width = ((width * correction_factor->width_multiplier) + correction_factor_approx_contribute) / correction_factor_divisor;
else
height = ((height * correction_factor->width_divisor) + correction_factor_approx_contribute) / correction_factor_divisor;
width /= correction_factor_3d;
}
}
void get_par_size(float &width, float &height, float multiplier_factor, const PARData *correction_factor) {
void get_par_size(float &width, float &height, float multiplier_factor, const PARData *correction_factor, bool divide_3d_par) {
width *= multiplier_factor;
height *= multiplier_factor;
float correction_factor_3d = 1.0;
if(divide_3d_par)
correction_factor_3d = 2.0;
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
else {
width /= correction_factor_3d;
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;
width /= correction_factor_3d;
}
}
SecondScreen3DRelativePosition get_second_screen_pos(ScreenInfo* info, ScreenType stype) {
if(info->match_bottom_pos_and_second_screen_pos && (stype == ScreenType::JOINT)) {
switch(info->bottom_pos) {
case UNDER_TOP:
return RIGHT_FIRST;
case ABOVE_TOP:
return LEFT_FIRST;
case RIGHT_TOP:
return UNDER_FIRST;
case LEFT_TOP:
return ABOVE_FIRST;
default:
return RIGHT_FIRST;
}
}
return info->second_screen_pos;
}
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))