Create initial main menu setup

This commit is contained in:
Lorenzooone
2024-05-05 22:58:24 +02:00
parent b73f8ff335
commit 0e94f3544a
16 changed files with 1182 additions and 784 deletions

View File

@@ -132,7 +132,7 @@ file(MAKE_DIRECTORY ${TOOLS_DATA_DIR})
set(OUTPUT_NAME cc3dsfs)
add_executable(CMakeBin2C tools/bin2c.cpp)
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/3dscapture.cpp source/conversions.cpp source/ConnectionMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp)
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/3dscapture.cpp source/conversions.cpp source/ConnectionMenu.cpp source/OptionSelectionMenu.cpp source/MainMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp)
add_dependencies(${OUTPUT_NAME} FTD3XX_BUILD_PROJECT CMakeBin2C)
target_link_libraries(${OUTPUT_NAME} PRIVATE sfml-graphics sfml-audio sfml-window sfml-system ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER}/${FTD3XX_LIB})
target_link_directories(${OUTPUT_NAME} PRIVATE ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER})

View File

@@ -1,55 +1,24 @@
#ifndef __CONNECTIONMENU_HPP
#define __CONNECTIONMENU_HPP
#include <SFML/Graphics.hpp>
#include <chrono>
#include "OptionSelectionMenu.hpp"
#include "TextRectangle.hpp"
#include "capture_structs.hpp"
#include "sfml_gfx_structs.hpp"
#define CONNECTION_NUM_ELEMENTS_PER_SCREEN 4
#define CONNECTION_NUM_PAGE_ELEMENTS 3
#define CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN (CONNECTION_NUM_ELEMENTS_PER_SCREEN + CONNECTION_NUM_PAGE_ELEMENTS)
#define CONNECTION_NUM_VERTICAL_SLICES (CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN - (CONNECTION_NUM_PAGE_ELEMENTS - 1))
class ConnectionMenu {
class ConnectionMenu : public OptionSelectionMenu {
public:
ConnectionMenu(bool font_load_success, sf::Font &text_font);
~ConnectionMenu();
bool poll(SFEvent &event_data);
void draw(float scaling_factor, sf::RenderTarget &window);
void prepare(float scaling_factor, int view_size_x, int view_size_y);
void insert_data(DevicesList *devices_list);
int selected_index = -1;
protected:
void reset_output_option();
void set_output_option(int index);
int get_num_options();
std::string get_string_option(int index);
void class_setup();
private:
struct ConnectionMenuData {
int page = 0;
int option_selected = -1;
bool enabled_labels[CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN];
int menu_width;
int menu_height;
int pos_x;
int pos_y;
};
std::chrono::time_point<std::chrono::high_resolution_clock> last_action_time;
const float action_timeout = 0.1;
int loaded_page = 0;
int option_selected = -1;
TextRectangle *labels[CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN];
bool selectable_labels[CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN];
ConnectionMenuData future_data;
ConnectionMenuData loaded_data;
DevicesList *devices_list;
bool can_execute_action();
void up_code();
void down_code();
void left_code();
void right_code();
void prepare_options();
void option_selection_handling();
void decrement_selected_option();
void increment_selected_option();
};
#endif

42
include/MainMenu.hpp Executable file
View File

@@ -0,0 +1,42 @@
#ifndef __MAINMENU_HPP
#define __MAINMENU_HPP
#include "OptionSelectionMenu.hpp"
#include <chrono>
#include "TextRectangle.hpp"
#include "sfml_gfx_structs.hpp"
#include "display_structs.hpp"
#define NUM_TOTAL_MAIN_MENU_OPTIONS 4
#define MAIN_NUM_ELEMENTS_PER_SCREEN 5
#define MAIN_NUM_PAGE_ELEMENTS 3
#define MAIN_NUM_ELEMENTS_DISPLAYED_PER_SCREEN (MAIN_NUM_ELEMENTS_PER_SCREEN + MAIN_NUM_PAGE_ELEMENTS)
#define MAIN_NUM_VERTICAL_SLICES (MAIN_NUM_ELEMENTS_DISPLAYED_PER_SCREEN - (MAIN_NUM_PAGE_ELEMENTS - 1))
enum MainMenuOutAction{
MAIN_MENU_NO_ACTION,
MAIN_MENU_OPEN,
MAIN_MENU_CLOSE_MENU,
MAIN_MENU_QUIT_APPLICATION,
};
class MainMenu : public OptionSelectionMenu {
public:
MainMenu(bool font_load_success, sf::Font &text_font);
~MainMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info, bool connected);
void insert_data(ScreenType s_type, bool is_fullscreen);
MainMenuOutAction selected_index = MainMenuOutAction::MAIN_MENU_NO_ACTION;
protected:
void reset_output_option();
void set_output_option(int index);
int get_num_options();
std::string get_string_option(int index);
void class_setup();
private:
int options_indexes[NUM_TOTAL_MAIN_MENU_OPTIONS];
int num_enabled_options;
};
#endif

72
include/OptionSelectionMenu.hpp Executable file
View File

@@ -0,0 +1,72 @@
#ifndef __OPTIONSELECTIONMENU_HPP
#define __OPTIONSELECTIONMENU_HPP
#include <SFML/Graphics.hpp>
#include <chrono>
#include "TextRectangle.hpp"
#include "sfml_gfx_structs.hpp"
class OptionSelectionMenu {
public:
OptionSelectionMenu();
~OptionSelectionMenu();
bool poll(SFEvent &event_data);
void draw(float scaling_factor, sf::RenderTarget &window);
void reset_data();
std::chrono::time_point<std::chrono::high_resolution_clock> last_input_processed_time;
protected:
int num_elements_per_screen = 1;
int num_page_elements = 3;
int num_elements_displayed_per_screen = num_elements_per_screen + num_page_elements;
int num_vertical_slices = (num_elements_displayed_per_screen - (num_page_elements - 1));
int num_elements_start_id = 0;
int num_page_elements_start_id = num_elements_per_screen + num_elements_start_id;
int prev_page_id = num_page_elements_start_id;
int info_page_id = num_page_elements_start_id + 1;
int next_page_id = num_page_elements_start_id + 2;
int min_elements_text_scaling_factor = 3;
int width_factor_menu = 1;
int width_divisor_menu = 1;
int base_height_factor_menu = 1;
int base_height_divisor_menu = 1;
float min_text_size = 0.3;
virtual void reset_output_option();
virtual void set_output_option(int index);
virtual int get_num_options();
virtual std::string get_string_option(int index);
virtual void class_setup();
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);
struct MenuData {
int page = 0;
int option_selected = -1;
int menu_width;
int menu_height;
int pos_x;
int pos_y;
};
MenuData future_data;
TextRectangle **labels;
bool *future_enabled_labels;
private:
std::chrono::time_point<std::chrono::high_resolution_clock> last_action_time;
const float action_timeout = 0.1;
int loaded_page = 0;
int option_selected = -1;
bool *selectable_labels;
bool *loaded_enabled_labels;
MenuData loaded_data;
void prepare_text_slices(int x_multiplier, int x_divisor, int y_multiplier, int y_divisor, int index, float text_scaling_factor);
bool can_execute_action();
void up_code();
void down_code();
void left_code();
void right_code();
void option_selection_handling();
void decrement_selected_option();
void increment_selected_option();
};
#endif

46
include/display_structs.hpp Executable file
View File

@@ -0,0 +1,46 @@
#ifndef __DISPLAY_STRUCTS_HPP
#define __DISPLAY_STRUCTS_HPP
#include "utils.hpp"
#include "hw_defs.hpp"
enum ScreenType { TOP, BOTTOM, JOINT };
enum Crop { DEFAULT_3DS, SPECIAL_DS, SCALED_DS, NATIVE_DS, SCALED_GBA, NATIVE_GBA, SCALED_GB, NATIVE_GB, SCALED_SNES, NATIVE_SNES, NATIVE_NES, CROP_END };
enum ParCorrection { PAR_NORMAL, PAR_SNES_HORIZONTAL, PAR_SNES_VERTICAL, PAR_END };
enum BottomRelativePosition { UNDER_TOP, LEFT_TOP, ABOVE_TOP, RIGHT_TOP, BOT_REL_POS_END };
enum OffsetAlgorithm { NO_DISTANCE, HALF_DISTANCE, MAX_DISTANCE, OFF_ALGO_END };
enum CurrMenuType { DEFAULT_MENU_TYPE, CONNECT_MENU_TYPE, MAIN_MENU_TYPE };
struct ScreenInfo {
bool is_blurred;
Crop crop_kind;
double scaling;
bool is_fullscreen;
BottomRelativePosition bottom_pos;
OffsetAlgorithm subscreen_offset_algorithm, subscreen_attached_offset_algorithm, total_offset_algorithm_x, total_offset_algorithm_y;
int top_rotation, bot_rotation;
bool show_mouse;
bool v_sync_enabled;
bool async;
int top_scaling, bot_scaling;
bool bfi;
double bfi_divider;
double menu_scaling_factor;
bool rounded_corners_fix;
ParCorrection top_par;
ParCorrection bot_par;
};
struct DisplayData {
bool split = false;
};
#pragma pack(push, 1)
struct PACKED VideoOutputData {
uint8_t screen_data[IN_VIDEO_SIZE][4];
};
#pragma pack(pop)
#endif

View File

@@ -9,60 +9,17 @@
#include "utils.hpp"
#include "audio_data.hpp"
#include "capture_structs.hpp"
#include "hw_defs.hpp"
#include "TextRectangle.hpp"
#include "sfml_gfx_structs.hpp"
#include "ConnectionMenu.hpp"
enum Crop { DEFAULT_3DS, SPECIAL_DS, SCALED_DS, NATIVE_DS, SCALED_GBA, NATIVE_GBA, SCALED_GB, NATIVE_GB, SCALED_SNES, NATIVE_SNES, NATIVE_NES, CROP_END };
enum ParCorrection { PAR_NORMAL, PAR_SNES_HORIZONTAL, PAR_SNES_VERTICAL, PAR_END };
enum BottomRelativePosition { UNDER_TOP, LEFT_TOP, ABOVE_TOP, RIGHT_TOP, BOT_REL_POS_END };
enum OffsetAlgorithm { NO_DISTANCE, HALF_DISTANCE, MAX_DISTANCE, OFF_ALGO_END };
enum CurrMenuType { DEFAULT_MENU_TYPE, CONNECT_MENU_TYPE };
struct ScreenInfo {
bool is_blurred;
Crop crop_kind;
double scaling;
bool is_fullscreen;
BottomRelativePosition bottom_pos;
OffsetAlgorithm subscreen_offset_algorithm, subscreen_attached_offset_algorithm, total_offset_algorithm_x, total_offset_algorithm_y;
int top_rotation, bot_rotation;
bool show_mouse;
bool v_sync_enabled;
bool async;
int top_scaling, bot_scaling;
bool bfi;
double bfi_divider;
double menu_scaling_factor;
bool rounded_corners_fix;
ParCorrection top_par;
ParCorrection bot_par;
};
struct DisplayData {
bool split = false;
CurrMenuType curr_menu = DEFAULT_MENU_TYPE;
};
#pragma pack(push, 1)
struct PACKED VideoOutputData {
uint8_t screen_data[IN_VIDEO_SIZE][4];
};
#pragma pack(pop)
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);
#include "MainMenu.hpp"
#include "display_structs.hpp"
class WindowScreen {
public:
enum ScreenType { TOP, BOTTOM, JOINT };
ScreenInfo m_info;
WindowScreen(WindowScreen::ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, AudioData* audio_data, std::mutex* events_access);
WindowScreen(ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, AudioData* audio_data, std::mutex* events_access);
~WindowScreen();
void build();
@@ -112,8 +69,10 @@ private:
std::chrono::time_point<std::chrono::high_resolution_clock> last_window_creation_time;
const float mouse_timeout = 5.0f;
const float v_sync_timeout = 5.0f;
CurrMenuType curr_menu = DEFAULT_MENU_TYPE;
CurrMenuType loaded_menu;
ConnectionMenu *connection_menu;
MainMenu *main_menu;
sf::Texture in_tex;
@@ -126,7 +85,7 @@ private:
sf::RectangleShape m_in_rect_top, m_in_rect_bot;
out_rect_data m_out_rect_top, m_out_rect_bot;
WindowScreen::ScreenType m_stype;
ScreenType m_stype;
std::queue<SFEvent> events_queue;
@@ -153,6 +112,7 @@ private:
void poll_window();
bool common_poll(SFEvent &event_data);
bool main_poll(SFEvent &event_data);
bool no_menu_poll(SFEvent &event_data);
void prepare_screen_rendering();
bool window_needs_work();
void window_factory(bool is_main_thread);
@@ -178,6 +138,7 @@ private:
sf::Vector2f getShownScreenSize(bool is_top, Crop &crop_kind);
void crop();
void setWinSize(bool is_main_thread);
void setup_main_menu();
void update_connection();
};
@@ -189,6 +150,9 @@ struct FrontendData {
bool reload;
};
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);
void get_par_size(float &width, float &height, float multiplier_factor, ParCorrection &correction_factor);
void get_par_size(int &width, int &height, float multiplier_factor, ParCorrection &correction_factor);
void default_sleep();

View File

@@ -5,7 +5,7 @@
#include <SFML/Graphics.hpp>
enum JoystickDirection {JOY_DIR_NONE, JOY_DIR_UP, JOY_DIR_DOWN, JOY_DIR_LEFT, JOY_DIR_RIGHT};
enum JoystickAction {JOY_ACTION_NONE, JOY_ACTION_CONFIRM, JOY_ACTION_NEGATE};
enum JoystickAction {JOY_ACTION_NONE, JOY_ACTION_CONFIRM, JOY_ACTION_NEGATE, JOY_ACTION_MENU};
struct out_rect_data {
sf::RectangleShape out_rect;

View File

@@ -21,6 +21,7 @@
#define USB_CHECKS_PER_SECOND ((USB_FPS + (USB_FPS / 12)) * USB_NUM_CHECKS)
bool is_big_endian(void);
std::string get_float_str_decimals(float value, int decimals);
class ConsumerMutex {
public:

View File

@@ -1,355 +1,51 @@
#include "ConnectionMenu.hpp"
#define CONNECTION_NUM_PAGE_ELEMENTS_START_ID CONNECTION_NUM_ELEMENTS_PER_SCREEN
#define CONNECTION_PREV_PAGE_ID (CONNECTION_NUM_PAGE_ELEMENTS_START_ID)
#define CONNECTION_INFO_PAGES_ID (CONNECTION_NUM_PAGE_ELEMENTS_START_ID + 1)
#define CONNECTION_NEXT_PAGE_ID (CONNECTION_NUM_PAGE_ELEMENTS_START_ID + 2)
ConnectionMenu::ConnectionMenu(bool font_load_success, sf::Font &text_font) {
for(int i = 0; i < CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN; i++) {
this->labels[i] = new TextRectangle(font_load_success, text_font);
this->labels[i]->setProportionalBox(false);
this->labels[i]->setText(std::to_string(i));
this->labels[i]->setShowText(true);
this->selectable_labels[i] = true;
this->future_data.enabled_labels[i] = true;
}
this->last_action_time = std::chrono::high_resolution_clock::now();
this->selectable_labels[CONNECTION_INFO_PAGES_ID] = false;
ConnectionMenu::ConnectionMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
}
ConnectionMenu::~ConnectionMenu() {
for(int i = 0; i < CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN; i++)
delete this->labels[i];
}
bool ConnectionMenu::can_execute_action() {
auto curr_time = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double> diff = curr_time - this->last_action_time;
if(diff.count() > this->action_timeout)
return true;
return false;
void ConnectionMenu::class_setup() {
this->num_elements_per_screen = 4;
this->num_page_elements = 3;
this->num_elements_displayed_per_screen = num_elements_per_screen + num_page_elements;
this->num_vertical_slices = (num_elements_displayed_per_screen - (num_page_elements - 1));
this->num_elements_start_id = 0;
this->num_page_elements_start_id = num_elements_per_screen + num_elements_start_id;
this->prev_page_id = num_page_elements_start_id;
this->info_page_id = num_page_elements_start_id + 1;
this->next_page_id = num_page_elements_start_id + 2;
this->min_elements_text_scaling_factor = num_elements_per_screen;
this->width_factor_menu = 16;
this->width_divisor_menu = 9;
this->base_height_factor_menu = 10;
this->base_height_divisor_menu = 6;
this->min_text_size = 0.3;
}
void ConnectionMenu::insert_data(DevicesList *devices_list) {
this->selected_index = -1;
this->future_data.option_selected = -1;
this->future_data.page = 0;
this->devices_list = devices_list;
this->prepare_options();
}
void ConnectionMenu::decrement_selected_option() {
do {
this->future_data.option_selected -= 1;
if(this->future_data.option_selected <= 0) {
this->future_data.option_selected = 0;
return;
}
if(this->future_data.option_selected >= CONNECTION_NUM_ELEMENTS_PER_SCREEN) {
this->future_data.option_selected = CONNECTION_NUM_ELEMENTS_PER_SCREEN - 1;
}
} while(!(this->selectable_labels[this->future_data.option_selected] && this->future_data.enabled_labels[this->future_data.option_selected]));
void ConnectionMenu::reset_output_option() {
this->selected_index = -1;
}
void ConnectionMenu::increment_selected_option() {
int starting_value = this->future_data.option_selected;
if(starting_value < 0){
this->future_data.option_selected = 0;
return;
}
do {
this->future_data.option_selected += 1;
if(this->future_data.option_selected >= CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN) {
this->future_data.option_selected = starting_value;
return;
}
} while(!(this->selectable_labels[this->future_data.option_selected] && this->future_data.enabled_labels[this->future_data.option_selected]));
void ConnectionMenu::set_output_option(int index) {
this->selected_index = index;
}
void ConnectionMenu::prepare_options() {
int num_pages = 1 + ((this->devices_list->numValidDevices - 1) / CONNECTION_NUM_ELEMENTS_PER_SCREEN);
if(this->future_data.page >= num_pages)
this->future_data.page = num_pages - 1;
int start = this->future_data.page * CONNECTION_NUM_ELEMENTS_PER_SCREEN;
int total_elements = this->devices_list->numValidDevices - start;
if(total_elements > CONNECTION_NUM_ELEMENTS_PER_SCREEN)
total_elements = CONNECTION_NUM_ELEMENTS_PER_SCREEN;
for(int i = 0; i < CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN; i++) {
this->future_data.enabled_labels[i] = false;
this->labels[i]->setShowText(false);
}
for(int i = 0; i < total_elements; i++) {
this->future_data.enabled_labels[i] = true;
this->labels[i]->setText(std::string(&this->devices_list->serialNumbers[SERIAL_NUMBER_SIZE * (i + start)]));
this->labels[i]->setShowText(true);
}
if(num_pages > 1) {
this->future_data.enabled_labels[CONNECTION_INFO_PAGES_ID] = true;
this->labels[CONNECTION_INFO_PAGES_ID]->setText(std::to_string(this->future_data.page + 1) + "/" + std::to_string(num_pages));
this->labels[CONNECTION_INFO_PAGES_ID]->setShowText(true);
if(this->future_data.page > 0) {
this->future_data.enabled_labels[CONNECTION_PREV_PAGE_ID] = true;
this->labels[CONNECTION_PREV_PAGE_ID]->setText("<");
this->labels[CONNECTION_PREV_PAGE_ID]->setShowText(true);
}
if(this->future_data.page < (num_pages - 1)) {
this->future_data.enabled_labels[CONNECTION_NEXT_PAGE_ID] = true;
this->labels[CONNECTION_NEXT_PAGE_ID]->setText(">");
this->labels[CONNECTION_NEXT_PAGE_ID]->setShowText(true);
}
}
if(!(this->selectable_labels[this->future_data.option_selected] && this->future_data.enabled_labels[this->future_data.option_selected])) {
this->future_data.option_selected = -1;
}
int ConnectionMenu::get_num_options() {
return this->devices_list->numValidDevices;
}
void ConnectionMenu::option_selection_handling() {
int old_loaded_page = this->future_data.page;
if(!(this->selectable_labels[this->future_data.option_selected] && this->future_data.enabled_labels[this->future_data.option_selected])) {
this->future_data.option_selected = -1;
return;
}
if(!this->can_execute_action())
return;
if(this->future_data.option_selected < CONNECTION_NUM_ELEMENTS_PER_SCREEN) {
this->selected_index = this->future_data.option_selected + (CONNECTION_NUM_ELEMENTS_PER_SCREEN * this->future_data.page);
this->last_action_time = std::chrono::high_resolution_clock::now();
}
else if((this->future_data.option_selected == CONNECTION_PREV_PAGE_ID) && this->future_data.page > 0)
this->future_data.page--;
else if((this->future_data.option_selected == CONNECTION_NEXT_PAGE_ID) && this->future_data.page < ((this->devices_list->numValidDevices - 1) / CONNECTION_NUM_ELEMENTS_PER_SCREEN))
this->future_data.page++;
if(old_loaded_page != this->future_data.page) {
this->prepare_options();
this->last_action_time = std::chrono::high_resolution_clock::now();
}
}
void ConnectionMenu::up_code() {
if(!this->can_execute_action())
return;
this->decrement_selected_option();
this->last_action_time = std::chrono::high_resolution_clock::now();
}
void ConnectionMenu::down_code() {
if(!this->can_execute_action())
return;
this->increment_selected_option();
this->last_action_time = std::chrono::high_resolution_clock::now();
}
void ConnectionMenu::left_code() {
if(!this->can_execute_action())
return;
if(this->selectable_labels[CONNECTION_PREV_PAGE_ID] && this->future_data.enabled_labels[CONNECTION_PREV_PAGE_ID]) {
if(this->future_data.option_selected == CONNECTION_PREV_PAGE_ID)
this->option_selection_handling();
else {
this->future_data.option_selected = CONNECTION_PREV_PAGE_ID;
this->last_action_time = std::chrono::high_resolution_clock::now();
}
}
}
void ConnectionMenu::right_code() {
if(!this->can_execute_action())
return;
if(this->selectable_labels[CONNECTION_NEXT_PAGE_ID] && this->future_data.enabled_labels[CONNECTION_NEXT_PAGE_ID]) {
if(this->future_data.option_selected == CONNECTION_NEXT_PAGE_ID)
this->option_selection_handling();
else {
this->future_data.option_selected = CONNECTION_NEXT_PAGE_ID;
this->last_action_time = std::chrono::high_resolution_clock::now();
}
}
}
bool ConnectionMenu::poll(SFEvent &event_data) {
bool consumed = true;
switch (event_data.type) {
case sf::Event::TextEntered:
switch (event_data.unicode) {
default:
consumed = false;
break;
}
break;
case sf::Event::KeyPressed:
switch (event_data.code) {
case sf::Keyboard::Up:
this->up_code();
break;
case sf::Keyboard::Down:
this->down_code();
break;
case sf::Keyboard::PageUp:
this->up_code();
break;
case sf::Keyboard::PageDown:
this->down_code();
break;
case sf::Keyboard::Left:
this->left_code();
break;
case sf::Keyboard::Right:
this->right_code();
break;
case sf::Keyboard::Enter:
this->option_selection_handling();
break;
default:
consumed = false;
break;
}
break;
case sf::Event::MouseMoved:
this->future_data.option_selected = -1;
for(int i = 0; i < CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN; i++) {
if(!(this->selectable_labels[i] && this->future_data.enabled_labels[i]))
continue;
if(this->labels[i]->isCoordInRectangle(event_data.mouse_x, event_data.mouse_y)) {
this->future_data.option_selected = i;
break;
}
}
break;
case sf::Event::MouseButtonPressed:
this->future_data.option_selected = -1;
for(int i = 0; i < CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN; i++) {
if(!(this->selectable_labels[i] && this->future_data.enabled_labels[i]))
continue;
if(this->labels[i]->isCoordInRectangle(event_data.mouse_x, event_data.mouse_y)) {
this->future_data.option_selected = i;
break;
}
}
if(this->future_data.option_selected == -1)
break;
if(event_data.mouse_button == sf::Mouse::Left)
this->option_selection_handling();
break;
case sf::Event::JoystickButtonPressed:
switch(get_joystick_action(event_data.joystickId, event_data.joy_button)) {
case JOY_ACTION_CONFIRM:
this->option_selection_handling();
break;
case JOY_ACTION_NEGATE:
this->option_selection_handling();
break;
default:
consumed = false;
break;
}
break;
case sf::Event::JoystickMoved:
switch(get_joystick_direction(event_data.joystickId, event_data.axis, event_data.position)) {
case JOY_DIR_UP:
this->up_code();
break;
case JOY_DIR_DOWN:
this->down_code();
break;
case JOY_DIR_LEFT:
this->left_code();
break;
case JOY_DIR_RIGHT:
this->right_code();
break;
default:
consumed = false;
break;
}
break;
default:
consumed = false;
break;
}
return consumed;
}
void ConnectionMenu::draw(float scaling_factor, sf::RenderTarget &window) {
sf::RectangleShape menu_rectangle(sf::Vector2f(this->loaded_data.menu_width, this->loaded_data.menu_height));
menu_rectangle.setFillColor(sf::Color(30, 30, 60, 192));
menu_rectangle.setPosition(this->loaded_data.pos_x, this->loaded_data.pos_y);
window.draw(menu_rectangle);
for(int i = 0; i < CONNECTION_NUM_ELEMENTS_DISPLAYED_PER_SCREEN; i++) {
if(this->loaded_data.enabled_labels[i])
this->labels[i]->draw(window);
}
std::string ConnectionMenu::get_string_option(int index) {
return std::string(&this->devices_list->serialNumbers[SERIAL_NUMBER_SIZE * index]);
}
void ConnectionMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y) {
int num_elements = 1;
for(int i = 1; i < CONNECTION_NUM_ELEMENTS_PER_SCREEN; i++)
if(this->future_data.enabled_labels[i])
num_elements++;
bool has_bottom = false;
for(int i = 0; i < CONNECTION_NUM_PAGE_ELEMENTS; i++)
if(this->future_data.enabled_labels[i + CONNECTION_NUM_PAGE_ELEMENTS_START_ID])
has_bottom = true;
if(has_bottom)
num_elements += 1;
const float base_height = (CONNECTION_NUM_VERTICAL_SLICES * (BASE_PIXEL_FONT_HEIGHT * 8)) / 6;
int max_width = (view_size_x * 9) / 10;
int max_height = (view_size_y * 9) / 10;
float max_scaling_factor = max_height / base_height;
if(menu_scaling_factor > max_scaling_factor)
menu_scaling_factor = max_scaling_factor;
if(menu_scaling_factor < 0.3)
menu_scaling_factor = 0.3;
int num_elements_text_scaling_factor = num_elements;
if(num_elements_text_scaling_factor < 3)
num_elements_text_scaling_factor = 3;
float text_scaling_factor = (menu_scaling_factor * CONNECTION_NUM_VERTICAL_SLICES) / num_elements_text_scaling_factor;
int menu_height = base_height * menu_scaling_factor;
int menu_width = (menu_height * 16) / 9;
if(menu_width > max_width)
menu_width = max_width;
int pos_x = (view_size_x - menu_width) / 2;
int pos_y = (view_size_y - menu_height) / 2;
int slice_y_size = menu_height / num_elements;
int slice_x_size = menu_width / CONNECTION_NUM_PAGE_ELEMENTS;
int num_rendered_y = 0;
for(int i = 0; i < CONNECTION_NUM_ELEMENTS_PER_SCREEN; i++) {
if(!this->future_data.enabled_labels[i])
continue;
this->labels[i]->setTextFactor(text_scaling_factor);
int x_size = menu_width;
int y_size = slice_y_size;
if(i == (num_elements - 1))
y_size = menu_height - (slice_y_size * (num_elements - 1));
this->labels[i]->setSize(x_size, y_size);
this->labels[i]->setPosition(pos_x, pos_y + (slice_y_size * i));
if(i == this->future_data.option_selected)
this->labels[i]->setRectangleKind(TEXT_KIND_SELECTED);
else
this->labels[i]->setRectangleKind(TEXT_KIND_NORMAL);
this->labels[i]->prepareRenderText();
++num_rendered_y;
}
for(int i = 0; i < CONNECTION_NUM_PAGE_ELEMENTS; i++) {
int index = i + CONNECTION_NUM_PAGE_ELEMENTS_START_ID;
if(!this->future_data.enabled_labels[index])
continue;
this->labels[index]->setTextFactor(text_scaling_factor);
int x_size = slice_x_size;
if(i == (CONNECTION_NUM_PAGE_ELEMENTS - 1))
x_size = menu_width - (slice_x_size * (CONNECTION_NUM_PAGE_ELEMENTS - 1));
int y_size = slice_y_size;
if(num_rendered_y == (num_elements - 1))
y_size = menu_height - (slice_y_size * (num_elements - 1));
this->labels[index]->setSize(x_size, y_size);
this->labels[index]->setPosition(pos_x + (slice_x_size * i), pos_y + (slice_y_size * num_rendered_y));
if(index == this->future_data.option_selected)
this->labels[index]->setRectangleKind(TEXT_KIND_SELECTED);
else
this->labels[index]->setRectangleKind(TEXT_KIND_NORMAL);
this->labels[index]->prepareRenderText();
}
this->loaded_data = this->future_data;
this->base_prepare(menu_scaling_factor, view_size_x, view_size_y);
}

99
source/MainMenu.cpp Executable file
View File

@@ -0,0 +1,99 @@
#include "MainMenu.hpp"
#define MAIN_NUM_PAGE_ELEMENTS_START_ID MAIN_NUM_ELEMENTS_PER_SCREEN
#define MAIN_PREV_PAGE_ID (MAIN_NUM_PAGE_ELEMENTS_START_ID)
#define MAIN_INFO_PAGES_ID (MAIN_NUM_PAGE_ELEMENTS_START_ID + 1)
#define MAIN_NEXT_PAGE_ID (MAIN_NUM_PAGE_ELEMENTS_START_ID + 2)
static std::string main_menu_option_strings[NUM_TOTAL_MAIN_MENU_OPTIONS] = {"Disconnect", "Connect", "Close Menu", "Quit Application"};
static bool usable_fullscreen[NUM_TOTAL_MAIN_MENU_OPTIONS] = {true, false, true, true};
static bool usable_normal_screen[NUM_TOTAL_MAIN_MENU_OPTIONS] = {true, false, true, true};
static bool usable_joint_screen[NUM_TOTAL_MAIN_MENU_OPTIONS] = {true, false, true, true};
static bool usable_top_screen[NUM_TOTAL_MAIN_MENU_OPTIONS] = {true, false, true, true};
static bool usable_bottom_screen[NUM_TOTAL_MAIN_MENU_OPTIONS] = {true, false, true, true};
static MainMenuOutAction main_menu_out_actions[NUM_TOTAL_MAIN_MENU_OPTIONS] = {MAIN_MENU_OPEN, MAIN_MENU_NO_ACTION, MAIN_MENU_CLOSE_MENU, MAIN_MENU_QUIT_APPLICATION};
MainMenu::MainMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
this->num_enabled_options = 0;
}
MainMenu::~MainMenu() {
}
void MainMenu::class_setup() {
this->num_elements_per_screen = 5;
this->num_page_elements = 3;
this->num_elements_displayed_per_screen = num_elements_per_screen + num_page_elements;
this->num_vertical_slices = (num_elements_displayed_per_screen - (num_page_elements - 1));
this->num_elements_start_id = 0;
this->num_page_elements_start_id = num_elements_per_screen + num_elements_start_id;
this->prev_page_id = num_page_elements_start_id;
this->info_page_id = num_page_elements_start_id + 1;
this->next_page_id = num_page_elements_start_id + 2;
this->min_elements_text_scaling_factor = this->num_vertical_slices;
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;
}
void MainMenu::insert_data(ScreenType s_type, bool is_fullscreen) {
bool *fullscreen_enabled_ptr = usable_fullscreen;
if(!is_fullscreen)
fullscreen_enabled_ptr = usable_normal_screen;
bool *screen_type_enabled_ptr = usable_joint_screen;
if(s_type == ScreenType::TOP)
screen_type_enabled_ptr = usable_top_screen;
if(s_type == ScreenType::BOTTOM)
screen_type_enabled_ptr = usable_bottom_screen;
this->num_enabled_options = 0;
for(int i = 0; i < NUM_TOTAL_MAIN_MENU_OPTIONS; i++) {
if(fullscreen_enabled_ptr[i] && screen_type_enabled_ptr[i]) {
this->options_indexes[this->num_enabled_options] = i;
this->num_enabled_options++;
}
}
this->prepare_options();
}
void MainMenu::reset_output_option() {
this->selected_index = MainMenuOutAction::MAIN_MENU_NO_ACTION;
}
void MainMenu::set_output_option(int index) {
this->selected_index = main_menu_out_actions[this->options_indexes[index]];
}
int MainMenu::get_num_options() {
return this->num_enabled_options;
}
std::string MainMenu::get_string_option(int index) {
return main_menu_option_strings[this->options_indexes[index]];
}
void MainMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info, bool connected) {
int num_pages = 1 + ((this->get_num_options() - 1) / this->num_elements_per_screen);
if(this->future_data.page >= num_pages)
this->future_data.page = num_pages - 1;
int start = this->future_data.page * this->num_elements_per_screen;
for(int i = 0; i < this->num_elements_per_screen; i++) {
if(!this->future_enabled_labels[i])
continue;
int option_index = this->options_indexes[start + i];
switch(main_menu_out_actions[option_index]) {
case MAIN_MENU_OPEN:
if(connected)
this->labels[i]->setText(main_menu_option_strings[option_index]);
else
this->labels[i]->setText(main_menu_option_strings[option_index + 1]);
break;
default:
break;
}
}
this->base_prepare(menu_scaling_factor, view_size_x, view_size_y);
}

401
source/OptionSelectionMenu.cpp Executable file
View File

@@ -0,0 +1,401 @@
#include "OptionSelectionMenu.hpp"
OptionSelectionMenu::OptionSelectionMenu() {
}
OptionSelectionMenu::~OptionSelectionMenu() {
for(int i = 0; i < this->num_elements_displayed_per_screen; i++)
delete this->labels[i];
delete []this->labels;
delete []this->selectable_labels;
delete []this->future_enabled_labels;
delete []this->loaded_enabled_labels;
}
void OptionSelectionMenu::initialize(bool font_load_success, sf::Font &text_font) {
this->class_setup();
this->labels = new TextRectangle*[this->num_elements_displayed_per_screen];
this->selectable_labels = new bool[this->num_elements_displayed_per_screen];
this->future_enabled_labels = new bool[this->num_elements_displayed_per_screen];
this->loaded_enabled_labels = new bool[this->num_elements_displayed_per_screen];
for(int i = 0; i < this->num_elements_displayed_per_screen; i++) {
this->labels[i] = new TextRectangle(font_load_success, text_font);
this->labels[i]->setProportionalBox(false);
this->labels[i]->setText(std::to_string(i));
this->labels[i]->setShowText(true);
this->selectable_labels[i] = true;
this->future_enabled_labels[i] = true;
}
this->future_data.menu_width = 1;
this->future_data.menu_height = 1;
this->future_data.pos_x = 0;
this->future_data.pos_y = 0;
this->last_action_time = std::chrono::high_resolution_clock::now();
this->last_input_processed_time = std::chrono::high_resolution_clock::now();
this->selectable_labels[this->info_page_id] = false;
}
void OptionSelectionMenu::class_setup() {
this->num_elements_per_screen = 1;
this->num_page_elements = 3;
this->num_elements_displayed_per_screen = num_elements_per_screen + num_page_elements;
this->num_vertical_slices = (num_elements_displayed_per_screen - (num_page_elements - 1));
this->num_elements_start_id = 0;
this->num_page_elements_start_id = num_elements_per_screen + num_elements_start_id;
this->prev_page_id = num_page_elements_start_id;
this->info_page_id = num_page_elements_start_id + 1;
this->next_page_id = num_page_elements_start_id + 2;
this->min_elements_text_scaling_factor = 3;
this->width_factor_menu = 1;
this->width_divisor_menu = 1;
this->base_height_factor_menu = 1;
this->base_height_divisor_menu = 1;
this->min_text_size = 0.3;
}
bool OptionSelectionMenu::can_execute_action() {
this->last_input_processed_time = std::chrono::high_resolution_clock::now();
auto curr_time = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double> diff = curr_time - this->last_action_time;
if(diff.count() > this->action_timeout)
return true;
return false;
}
void OptionSelectionMenu::reset_data() {
this->last_input_processed_time = std::chrono::high_resolution_clock::now();
this->reset_output_option();
this->future_data.option_selected = -1;
this->future_data.page = 0;
}
void OptionSelectionMenu::decrement_selected_option() {
do {
this->future_data.option_selected -= 1;
if(this->future_data.option_selected <= 0) {
this->future_data.option_selected = 0;
return;
}
if((this->future_data.option_selected < (this->num_page_elements_start_id + this->num_page_elements)) && (this->future_data.option_selected >= num_page_elements_start_id)) {
this->future_data.option_selected = this->num_page_elements_start_id - 1;
}
} while(!(this->selectable_labels[this->future_data.option_selected] && this->future_enabled_labels[this->future_data.option_selected]));
}
void OptionSelectionMenu::increment_selected_option() {
int starting_value = this->future_data.option_selected;
if(starting_value < 0){
this->future_data.option_selected = 0;
return;
}
do {
this->future_data.option_selected += 1;
if(this->future_data.option_selected >= this->num_elements_displayed_per_screen) {
this->future_data.option_selected = starting_value;
return;
}
} while(!(this->selectable_labels[this->future_data.option_selected] && this->future_enabled_labels[this->future_data.option_selected]));
}
void OptionSelectionMenu::reset_output_option() {
}
void OptionSelectionMenu::set_output_option(int index) {
}
int OptionSelectionMenu::get_num_options() {
return this->num_elements_per_screen;
}
std::string OptionSelectionMenu::get_string_option(int index) {
return "Sample Text";
}
void OptionSelectionMenu::prepare_options() {
int num_pages = 1 + ((this->get_num_options() - 1) / this->num_elements_per_screen);
if(this->future_data.page >= num_pages)
this->future_data.page = num_pages - 1;
int start = this->future_data.page * this->num_elements_per_screen;
int total_elements = this->get_num_options() - start;
if(total_elements > this->num_elements_per_screen)
total_elements = this->num_elements_per_screen;
for(int i = 0; i < this->num_elements_displayed_per_screen; i++) {
this->future_enabled_labels[i] = false;
this->labels[i]->setShowText(false);
}
for(int i = 0; i < total_elements; i++) {
this->future_enabled_labels[i] = true;
this->labels[i]->setText(this->get_string_option(i + start));
this->labels[i]->setShowText(true);
}
if(num_pages > 1) {
this->future_enabled_labels[this->info_page_id] = true;
this->labels[this->info_page_id]->setText(std::to_string(this->future_data.page + 1) + "/" + std::to_string(num_pages));
this->labels[this->info_page_id]->setShowText(true);
if(this->future_data.page > 0) {
this->future_enabled_labels[this->prev_page_id] = true;
this->labels[this->prev_page_id]->setText("<");
this->labels[this->prev_page_id]->setShowText(true);
}
if(this->future_data.page < (num_pages - 1)) {
this->future_enabled_labels[this->next_page_id] = true;
this->labels[this->next_page_id]->setText(">");
this->labels[this->next_page_id]->setShowText(true);
}
}
if(!(this->selectable_labels[this->future_data.option_selected] && this->future_enabled_labels[this->future_data.option_selected])) {
this->future_data.option_selected = -1;
}
}
void OptionSelectionMenu::option_selection_handling() {
int old_loaded_page = this->future_data.page;
if(!(this->selectable_labels[this->future_data.option_selected] && this->future_enabled_labels[this->future_data.option_selected])) {
this->future_data.option_selected = -1;
return;
}
if(!this->can_execute_action())
return;
if(this->future_data.option_selected < this->num_elements_per_screen) {
this->set_output_option(this->future_data.option_selected + (this->num_elements_per_screen * this->future_data.page));
this->last_action_time = std::chrono::high_resolution_clock::now();
}
else if((this->future_data.option_selected == this->prev_page_id) && this->future_data.page > 0)
this->future_data.page--;
else if((this->future_data.option_selected == this->next_page_id) && this->future_data.page < ((this->get_num_options() - 1) / this->num_elements_per_screen))
this->future_data.page++;
if(old_loaded_page != this->future_data.page) {
this->prepare_options();
this->last_action_time = std::chrono::high_resolution_clock::now();
}
}
void OptionSelectionMenu::up_code() {
if(!this->can_execute_action())
return;
this->decrement_selected_option();
this->last_action_time = std::chrono::high_resolution_clock::now();
}
void OptionSelectionMenu::down_code() {
if(!this->can_execute_action())
return;
this->increment_selected_option();
this->last_action_time = std::chrono::high_resolution_clock::now();
}
void OptionSelectionMenu::left_code() {
if(!this->can_execute_action())
return;
if(this->selectable_labels[this->prev_page_id] && this->future_enabled_labels[this->prev_page_id]) {
if(this->future_data.option_selected == this->prev_page_id)
this->option_selection_handling();
else {
this->future_data.option_selected = this->prev_page_id;
this->last_action_time = std::chrono::high_resolution_clock::now();
}
}
}
void OptionSelectionMenu::right_code() {
if(!this->can_execute_action())
return;
if(this->selectable_labels[this->next_page_id] && this->future_enabled_labels[this->next_page_id]) {
if(this->future_data.option_selected == this->next_page_id)
this->option_selection_handling();
else {
this->future_data.option_selected = this->next_page_id;
this->last_action_time = std::chrono::high_resolution_clock::now();
}
}
}
bool OptionSelectionMenu::poll(SFEvent &event_data) {
bool consumed = true;
switch (event_data.type) {
case sf::Event::TextEntered:
switch (event_data.unicode) {
default:
consumed = false;
break;
}
break;
case sf::Event::KeyPressed:
switch (event_data.code) {
case sf::Keyboard::Up:
this->up_code();
break;
case sf::Keyboard::Down:
this->down_code();
break;
case sf::Keyboard::PageUp:
this->up_code();
break;
case sf::Keyboard::PageDown:
this->down_code();
break;
case sf::Keyboard::Left:
this->left_code();
break;
case sf::Keyboard::Right:
this->right_code();
break;
case sf::Keyboard::Enter:
this->option_selection_handling();
break;
default:
consumed = false;
break;
}
break;
case sf::Event::MouseMoved:
this->future_data.option_selected = -1;
for(int i = 0; i < this->num_elements_displayed_per_screen; i++) {
if(!(this->selectable_labels[i] && this->future_enabled_labels[i]))
continue;
if(this->labels[i]->isCoordInRectangle(event_data.mouse_x, event_data.mouse_y)) {
this->future_data.option_selected = i;
this->last_input_processed_time = std::chrono::high_resolution_clock::now();
break;
}
}
break;
case sf::Event::MouseButtonPressed:
this->future_data.option_selected = -1;
for(int i = 0; i < this->num_elements_displayed_per_screen; i++) {
if(!(this->selectable_labels[i] && this->future_enabled_labels[i]))
continue;
if(this->labels[i]->isCoordInRectangle(event_data.mouse_x, event_data.mouse_y)) {
this->future_data.option_selected = i;
break;
}
}
if(this->future_data.option_selected == -1)
break;
if(event_data.mouse_button == sf::Mouse::Left)
this->option_selection_handling();
break;
case sf::Event::JoystickButtonPressed:
switch(get_joystick_action(event_data.joystickId, event_data.joy_button)) {
case JOY_ACTION_CONFIRM:
this->option_selection_handling();
break;
case JOY_ACTION_NEGATE:
this->option_selection_handling();
break;
default:
consumed = false;
break;
}
break;
case sf::Event::JoystickMoved:
switch(get_joystick_direction(event_data.joystickId, event_data.axis, event_data.position)) {
case JOY_DIR_UP:
this->up_code();
break;
case JOY_DIR_DOWN:
this->down_code();
break;
case JOY_DIR_LEFT:
this->left_code();
break;
case JOY_DIR_RIGHT:
this->right_code();
break;
default:
consumed = false;
break;
}
break;
default:
consumed = false;
break;
}
return consumed;
}
void OptionSelectionMenu::draw(float scaling_factor, sf::RenderTarget &window) {
sf::RectangleShape menu_rectangle(sf::Vector2f(this->loaded_data.menu_width, this->loaded_data.menu_height));
menu_rectangle.setFillColor(sf::Color(30, 30, 60, 192));
menu_rectangle.setPosition(this->loaded_data.pos_x, this->loaded_data.pos_y);
window.draw(menu_rectangle);
for(int i = 0; i < this->num_elements_displayed_per_screen; i++) {
if(this->loaded_enabled_labels[i])
this->labels[i]->draw(window);
}
}
void OptionSelectionMenu::prepare_text_slices(int x_multiplier, int x_divisor, int y_multiplier, int y_divisor, int index, float text_scaling_factor) {
this->labels[index]->setTextFactor(text_scaling_factor);
int x_base_pos = (this->future_data.menu_width * x_multiplier) / x_divisor;
int y_base_pos = (this->future_data.menu_height * y_multiplier) / y_divisor;
int x_size = ((this->future_data.menu_width * (x_multiplier + 1)) / x_divisor) - x_base_pos;
int y_size = ((this->future_data.menu_height * (y_multiplier + 1)) / y_divisor) - y_base_pos;
this->labels[index]->setSize(x_size, y_size);
this->labels[index]->setPosition(this->future_data.pos_x + x_base_pos, this->future_data.pos_y + y_base_pos);
if(index == this->future_data.option_selected)
this->labels[index]->setRectangleKind(TEXT_KIND_SELECTED);
else
this->labels[index]->setRectangleKind(TEXT_KIND_NORMAL);
this->labels[index]->prepareRenderText();
}
void OptionSelectionMenu::base_prepare(float menu_scaling_factor, int view_size_x, int view_size_y) {
int num_elements = 0;
for(int i = 0; i < this->num_elements_per_screen; i++)
if(this->future_enabled_labels[i])
num_elements++;
bool has_bottom = false;
for(int i = 0; i < this->num_page_elements; i++)
if(this->future_enabled_labels[i + this->num_page_elements_start_id])
has_bottom = true;
if(has_bottom)
num_elements += 1;
const float base_height = (this->num_vertical_slices * BASE_PIXEL_FONT_HEIGHT * 10) / 9;
int max_width = (view_size_x * 9) / 10;
int max_height = (view_size_y * 9) / 10;
float max_scaling_factor = max_height / base_height;
float final_menu_scaling_factor = (menu_scaling_factor * this->base_height_factor_menu) / this->base_height_divisor_menu;
if(menu_scaling_factor > max_scaling_factor)
menu_scaling_factor = max_scaling_factor;
if(final_menu_scaling_factor > max_scaling_factor)
final_menu_scaling_factor = max_scaling_factor;
if(menu_scaling_factor < this->min_text_size)
menu_scaling_factor = this->min_text_size;
if(final_menu_scaling_factor < this->min_text_size)
final_menu_scaling_factor = this->min_text_size;
int num_elements_text_scaling_factor = num_elements;
if(num_elements_text_scaling_factor < this->min_elements_text_scaling_factor)
num_elements_text_scaling_factor = this->min_elements_text_scaling_factor;
float text_scaling_factor = (menu_scaling_factor * this->num_vertical_slices) / num_elements_text_scaling_factor;
this->future_data.menu_height = base_height * final_menu_scaling_factor;
this->future_data.menu_width = (this->future_data.menu_height * this->width_factor_menu) / this->width_divisor_menu;
if(this->future_data.menu_width > max_width)
this->future_data.menu_width = max_width;
this->future_data.pos_x = (view_size_x - this->future_data.menu_width) / 2;
this->future_data.pos_y = (view_size_y - this->future_data.menu_height) / 2;
int slice_y_size = this->future_data.menu_height / num_elements;
int slice_x_size = this->future_data.menu_width / this->num_page_elements;
int num_rendered_y = 0;
for(int i = 0; i < this->num_elements_per_screen; i++) {
int index = i;
if(this->future_enabled_labels[index]) {
this->prepare_text_slices(0, 1, num_rendered_y, num_elements, index, text_scaling_factor);
++num_rendered_y;
}
}
for(int i = 0; i < this->num_page_elements; i++) {
int index = i + this->num_page_elements_start_id;
if(this->future_enabled_labels[index]){
this->prepare_text_slices(i, this->num_page_elements, num_rendered_y, num_elements, index, text_scaling_factor);
}
}
if(has_bottom)
++num_rendered_y;
this->loaded_data = this->future_data;
for(int i = 0; i < this->num_elements_displayed_per_screen; i++)
this->loaded_enabled_labels[i] = this->future_enabled_labels[i];
}

View File

@@ -93,14 +93,17 @@ void TextRectangle::prepareRenderText() {
}
void TextRectangle::setText(std::string text) {
if(this->future_data.printed_text != text)
this->future_data.render_text = true;
this->future_data.printed_text = text;
this->future_data.render_text = true;
}
void TextRectangle::setShowText(bool show_text) {
this->future_data.show_text = show_text;
if(!this->future_data.show_text)
this->startTimer(false);
if(this->future_data.show_text)
this->future_data.render_text = true;
}
void TextRectangle::draw(sf::RenderTarget &window) {
@@ -214,6 +217,7 @@ void TextRectangle::updateText(int x_limit) {
this->actual_text.setFillColor(sf::Color::White);
// set the text style
//this->actual_text.setStyle(sf::Text::Bold);
this->actual_text.setPosition(0, 0);
this->setTextWithLineWrapping(x_limit);
sf::FloatRect globalBounds;
if(this->loaded_data.proportional_box) {

View File

@@ -1,7 +1,6 @@
#include "frontend.hpp"
#include <cstring>
#include <cmath>
#include "font_ttf.h"
#define LEFT_ROUNDED_PADDING 5
@@ -23,7 +22,7 @@ static std::string crop_names[] = {"3DS", "16:10", "Scaled DS", "Native DS", "Sc
static std::string par_width_names[] = {"1:1", "SNES Horizontal", "SNES Vertical"};
WindowScreen::WindowScreen(WindowScreen::ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, AudioData* audio_data, std::mutex* events_access) {
WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, AudioData* audio_data, std::mutex* events_access) {
this->m_stype = stype;
this->events_access = events_access;
this->m_prepare_save = 0;
@@ -34,6 +33,7 @@ WindowScreen::WindowScreen(WindowScreen::ScreenType stype, CaptureStatus* captur
this->font_load_success = this->text_font.loadFromMemory(font_ttf, font_ttf_len);
this->notification = new TextRectangle(this->font_load_success, this->text_font);
this->connection_menu = new ConnectionMenu(this->font_load_success, this->text_font);
this->main_menu = new MainMenu(this->font_load_success, this->text_font);
this->in_tex.create(IN_VIDEO_WIDTH, IN_VIDEO_HEIGHT);
this->m_in_rect_top.setTexture(&this->in_tex);
this->m_in_rect_bot.setTexture(&this->in_tex);
@@ -45,9 +45,9 @@ WindowScreen::WindowScreen(WindowScreen::ScreenType stype, CaptureStatus* captur
this->done_display = true;
this->saved_buf = new VideoOutputData;
this->win_title = NAME;
if(this->m_stype == WindowScreen::ScreenType::TOP)
if(this->m_stype == ScreenType::TOP)
this->win_title += "_top";
if(this->m_stype == WindowScreen::ScreenType::BOTTOM)
if(this->m_stype == ScreenType::BOTTOM)
this->win_title += "_bot";
this->last_connected_status = false;
this->capture_status = capture_status;
@@ -57,6 +57,7 @@ WindowScreen::~WindowScreen() {
delete this->saved_buf;
delete this->notification;
delete this->connection_menu;
delete this->main_menu;
}
void WindowScreen::build() {
@@ -64,7 +65,7 @@ void WindowScreen::build() {
sf::Vector2f bot_screen_size = sf::Vector2f(BOT_WIDTH_3DS, HEIGHT_3DS);
int width = TOP_WIDTH_3DS;
if(this->m_stype == WindowScreen::ScreenType::BOTTOM)
if(this->m_stype == ScreenType::BOTTOM)
width = BOT_WIDTH_3DS;
this->reload();
@@ -93,333 +94,396 @@ void WindowScreen::reload() {
bool WindowScreen::common_poll(SFEvent &event_data) {
double old_scaling = 0.0;
bool consumed = true;
switch (event_data.type) {
case sf::Event::Closed:
this->m_prepare_quit = true;
break;
case sf::Event::TextEntered:
switch (event_data.unicode) {
case 's':
this->m_info.is_fullscreen = false;
this->display_data->split = !this->display_data->split;
break;
case 'f':
this->m_info.is_fullscreen = !this->m_info.is_fullscreen;
this->create_window(true);
break;
case 'a':
this->m_info.async = !this->m_info.async;
this->print_notification_on_off("Async", this->m_info.async);
break;
case 'v':
this->m_info.v_sync_enabled = !this->m_info.v_sync_enabled;
this->print_notification_on_off("VSync", this->m_info.v_sync_enabled);
break;
case 'z':
old_scaling = this->m_info.menu_scaling_factor;
this->m_info.menu_scaling_factor -= 0.1;
if(this->m_info.menu_scaling_factor < 0.35)
this->m_info.menu_scaling_factor = 0.3;
if(old_scaling != this->m_info.menu_scaling_factor) {
this->print_notification_float("Menu Scaling", this->m_info.menu_scaling_factor, 1);
}
break;
case 'x':
old_scaling = this->m_info.menu_scaling_factor;
this->m_info.menu_scaling_factor += 0.1;
if(this->m_info.menu_scaling_factor > 4.95)
this->m_info.menu_scaling_factor = 5.0;
if(old_scaling != this->m_info.menu_scaling_factor) {
this->print_notification_float("Menu Scaling", this->m_info.menu_scaling_factor, 1);
}
break;
case '-':
if(this->m_info.is_fullscreen)
break;
old_scaling = this->m_info.scaling;
this->m_info.scaling -= 0.5;
if (this->m_info.scaling < 1.25)
this->m_info.scaling = 1.0;
if(old_scaling != this->m_info.scaling) {
this->print_notification_float("Scaling", this->m_info.scaling, 1);
this->future_operations.call_screen_settings_update = true;
}
break;
case '0':
if(this->m_info.is_fullscreen)
break;
old_scaling = this->m_info.scaling;
this->m_info.scaling += 0.5;
if (this->m_info.scaling > 44.75)
this->m_info.scaling = 45.0;
if(old_scaling != this->m_info.scaling) {
this->print_notification_float("Scaling", this->m_info.scaling, 1);
this->future_operations.call_screen_settings_update = true;
}
break;
default:
consumed = false;
break;
}
break;
case sf::Event::KeyPressed:
switch (event_data.code) {
case sf::Keyboard::Escape:
switch(event_data.type) {
case sf::Event::Closed:
this->m_prepare_quit = true;
break;
case sf::Event::TextEntered:
switch(event_data.unicode) {
case 's':
if(this->curr_menu != CONNECT_MENU_TYPE)
this->curr_menu = DEFAULT_MENU_TYPE;
this->m_info.is_fullscreen = false;
this->display_data->split = !this->display_data->split;
break;
case 'f':
if(this->curr_menu != CONNECT_MENU_TYPE)
this->curr_menu = DEFAULT_MENU_TYPE;
this->m_info.is_fullscreen = !this->m_info.is_fullscreen;
this->create_window(true);
break;
case 'a':
this->m_info.async = !this->m_info.async;
this->print_notification_on_off("Async", this->m_info.async);
break;
case 'v':
this->m_info.v_sync_enabled = !this->m_info.v_sync_enabled;
this->print_notification_on_off("VSync", this->m_info.v_sync_enabled);
break;
case 'z':
old_scaling = this->m_info.menu_scaling_factor;
this->m_info.menu_scaling_factor -= 0.1;
if(this->m_info.menu_scaling_factor < 0.35)
this->m_info.menu_scaling_factor = 0.3;
if(old_scaling != this->m_info.menu_scaling_factor) {
this->print_notification_float("Menu Scaling", this->m_info.menu_scaling_factor, 1);
}
break;
case 'x':
old_scaling = this->m_info.menu_scaling_factor;
this->m_info.menu_scaling_factor += 0.1;
if(this->m_info.menu_scaling_factor > 4.95)
this->m_info.menu_scaling_factor = 5.0;
if(old_scaling != this->m_info.menu_scaling_factor) {
this->print_notification_float("Menu Scaling", this->m_info.menu_scaling_factor, 1);
}
break;
case '-':
if(this->m_info.is_fullscreen)
break;
old_scaling = this->m_info.scaling;
this->m_info.scaling -= 0.5;
if (this->m_info.scaling < 1.25)
this->m_info.scaling = 1.0;
if(old_scaling != this->m_info.scaling) {
this->print_notification_float("Scaling", this->m_info.scaling, 1);
this->future_operations.call_screen_settings_update = true;
}
break;
case '0':
if(this->m_info.is_fullscreen)
break;
old_scaling = this->m_info.scaling;
this->m_info.scaling += 0.5;
if (this->m_info.scaling > 44.75)
this->m_info.scaling = 45.0;
if(old_scaling != this->m_info.scaling) {
this->print_notification_float("Scaling", this->m_info.scaling, 1);
this->future_operations.call_screen_settings_update = true;
}
break;
default:
consumed = false;
break;
}
break;
case sf::Event::KeyPressed:
switch(event_data.code) {
case sf::Keyboard::Escape:
this->m_prepare_quit = true;
break;
default:
consumed = false;
break;
}
break;
case sf::Event::MouseMoved:
if(this->m_info.is_fullscreen) {
this->m_info.show_mouse = true;
this->last_mouse_action_time = std::chrono::high_resolution_clock::now();
}
consumed = false;
break;
case sf::Event::MouseButtonPressed:
if(this->m_info.is_fullscreen) {
this->m_info.show_mouse = true;
this->last_mouse_action_time = std::chrono::high_resolution_clock::now();
}
consumed = false;
break;
case sf::Event::MouseButtonReleased:
if(this->m_info.is_fullscreen) {
this->m_info.show_mouse = true;
this->last_mouse_action_time = std::chrono::high_resolution_clock::now();
}
consumed = false;
break;
case sf::Event::JoystickButtonPressed:
consumed = false;
break;
case sf::Event::JoystickMoved:
consumed = false;
break;
default:
consumed = false;
break;
}
}
return consumed;
}
break;
case sf::Event::MouseMoved:
if(this->m_info.is_fullscreen) {
this->m_info.show_mouse = true;
this->last_mouse_action_time = std::chrono::high_resolution_clock::now();
}
consumed = false;
break;
case sf::Event::MouseButtonPressed:
if(this->m_info.is_fullscreen) {
this->m_info.show_mouse = true;
this->last_mouse_action_time = std::chrono::high_resolution_clock::now();
}
consumed = false;
break;
case sf::Event::MouseButtonReleased:
if(this->m_info.is_fullscreen) {
this->m_info.show_mouse = true;
this->last_mouse_action_time = std::chrono::high_resolution_clock::now();
}
consumed = false;
break;
case sf::Event::JoystickButtonPressed:
consumed = false;
break;
case sf::Event::JoystickMoved:
consumed = false;
break;
default:
consumed = false;
break;
void WindowScreen::setup_main_menu() {
if(this->curr_menu != MAIN_MENU_TYPE) {
this->curr_menu = MAIN_MENU_TYPE;
this->main_menu->reset_data();
this->main_menu->insert_data(this->m_stype, this->m_info.is_fullscreen);
}
}
bool WindowScreen::no_menu_poll(SFEvent &event_data) {
bool consumed = true;
switch(event_data.type) {
case sf::Event::TextEntered:
switch(event_data.unicode) {
default:
consumed = false;
break;
}
break;
case sf::Event::KeyPressed:
switch(event_data.code) {
case sf::Keyboard::Enter:
this->setup_main_menu();
break;
default:
consumed = false;
break;
}
break;
case sf::Event::MouseMoved:
consumed = false;
break;
case sf::Event::MouseButtonPressed:
if(event_data.mouse_button == sf::Mouse::Right)
this->setup_main_menu();
else
consumed = false;
break;
case sf::Event::MouseButtonReleased:
consumed = false;
break;
case sf::Event::JoystickButtonPressed:switch(get_joystick_action(event_data.joystickId, event_data.joy_button)) {
case JOY_ACTION_MENU:
this->setup_main_menu();
break;
default:
consumed = false;
break;
}
break;
case sf::Event::JoystickMoved:
consumed = false;
break;
default:
consumed = false;
break;
}
return consumed;
}
bool WindowScreen::main_poll(SFEvent &event_data) {
bool consumed = true;
switch (event_data.type) {
case sf::Event::TextEntered:
switch (event_data.unicode) {
case 'c':
if(this->m_stype == WindowScreen::ScreenType::BOTTOM) {
if(this->m_info.crop_kind == Crop::DEFAULT_3DS)
this->m_info.crop_kind = Crop::NATIVE_DS;
else
this->m_info.crop_kind = Crop::DEFAULT_3DS;
switch(event_data.type) {
case sf::Event::TextEntered:
switch(event_data.unicode) {
case 'c':
if(this->m_stype == ScreenType::BOTTOM) {
if(this->m_info.crop_kind == Crop::DEFAULT_3DS)
this->m_info.crop_kind = Crop::NATIVE_DS;
else
this->m_info.crop_kind = Crop::DEFAULT_3DS;
}
else {
this->m_info.crop_kind = static_cast<Crop>((this->m_info.crop_kind + 1) % Crop::CROP_END);
}
this->print_notification("Crop: " + crop_names[this->m_info.crop_kind]);
this->prepare_size_ratios(false, false);
this->future_operations.call_crop = true;
break;
case 'b':
this->m_info.is_blurred = !this->m_info.is_blurred;
this->future_operations.call_blur = true;
this->print_notification_on_off("Blur", this->m_info.is_blurred);
break;
case 'i':
this->m_info.bfi = !this->m_info.bfi;
this->print_notification_on_off("BFI", this->m_info.bfi);
break;
case 'o':
this->m_prepare_open = true;
break;
case 't':
this->m_info.bottom_pos = static_cast<BottomRelativePosition>((this->m_info.bottom_pos + 1) % (BottomRelativePosition::BOT_REL_POS_END));
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
break;
case '6':
this->m_info.subscreen_offset_algorithm = static_cast<OffsetAlgorithm>((this->m_info.subscreen_offset_algorithm + 1) % (OffsetAlgorithm::OFF_ALGO_END));
this->future_operations.call_screen_settings_update = true;
break;
case '7':
this->m_info.subscreen_attached_offset_algorithm = static_cast<OffsetAlgorithm>((this->m_info.subscreen_attached_offset_algorithm + 1) % (OffsetAlgorithm::OFF_ALGO_END));
this->future_operations.call_screen_settings_update = true;
break;
case '4':
this->m_info.total_offset_algorithm_x = static_cast<OffsetAlgorithm>((this->m_info.total_offset_algorithm_x + 1) % (OffsetAlgorithm::OFF_ALGO_END));
this->future_operations.call_screen_settings_update = true;
break;
case '5':
this->m_info.total_offset_algorithm_y = static_cast<OffsetAlgorithm>((this->m_info.total_offset_algorithm_y + 1) % (OffsetAlgorithm::OFF_ALGO_END));
this->future_operations.call_screen_settings_update = true;
break;
case 'y':
this->prepare_size_ratios(true, false);
this->future_operations.call_screen_settings_update = true;
break;
case 'u':
this->prepare_size_ratios(false, true);
this->future_operations.call_screen_settings_update = true;
break;
case '8':
this->m_info.top_rotation = (this->m_info.top_rotation + 270) % 360;
this->m_info.bot_rotation = (this->m_info.bot_rotation + 270) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case '9':
this->m_info.top_rotation = (this->m_info.top_rotation + 90) % 360;
this->m_info.bot_rotation = (this->m_info.bot_rotation + 90) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'h':
this->m_info.top_rotation = (this->m_info.top_rotation + 270) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'j':
this->m_info.top_rotation = (this->m_info.top_rotation + 90) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'k':
this->m_info.bot_rotation = (this->m_info.bot_rotation + 270) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'l':
this->m_info.bot_rotation = (this->m_info.bot_rotation + 90) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'r':
if(this->m_info.is_fullscreen)
break;
this->m_info.rounded_corners_fix = !this->m_info.rounded_corners_fix;
this->future_operations.call_screen_settings_update = true;
this->print_notification_on_off("Extra Padding", this->m_info.rounded_corners_fix);
break;
case '2':
if(this->m_stype == ScreenType::BOTTOM)
break;
this->m_info.top_par = static_cast<ParCorrection>((this->m_info.top_par + 1) % (ParCorrection::PAR_END));
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
this->print_notification("Top PAR: " + par_width_names[this->m_info.top_par]);
break;
case '3':
if(this->m_stype == ScreenType::TOP)
break;
this->m_info.bot_par = static_cast<ParCorrection>((this->m_info.bot_par + 1) % (ParCorrection::PAR_END));
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
this->print_notification("Bottom PAR: " + par_width_names[this->m_info.bot_par]);
break;
case 'm':
audio_data->change_audio_mute();
break;
case ',':
audio_data->change_audio_volume(false);
break;
case '.':
audio_data->change_audio_volume(true);
break;
default:
consumed = false;
break;
}
else {
this->m_info.crop_kind = static_cast<Crop>((this->m_info.crop_kind + 1) % Crop::CROP_END);
break;
case sf::Event::KeyPressed:
switch(event_data.code) {
case sf::Keyboard::F1:
case sf::Keyboard::F2:
case sf::Keyboard::F3:
case sf::Keyboard::F4:
this->m_prepare_load = event_data.code - sf::Keyboard::F1 + 1;
break;
case sf::Keyboard::F5:
case sf::Keyboard::F6:
case sf::Keyboard::F7:
case sf::Keyboard::F8:
this->m_prepare_save = event_data.code - sf::Keyboard::F5 + 1;
break;
default:
consumed = false;
break;
}
this->print_notification("Crop: " + crop_names[this->m_info.crop_kind]);
this->prepare_size_ratios(false, false);
this->future_operations.call_crop = true;
break;
case 'b':
this->m_info.is_blurred = !this->m_info.is_blurred;
this->future_operations.call_blur = true;
this->print_notification_on_off("Blur", this->m_info.is_blurred);
break;
case 'i':
this->m_info.bfi = !this->m_info.bfi;
this->print_notification_on_off("BFI", this->m_info.bfi);
break;
case 'o':
this->m_prepare_open = true;
break;
case 't':
this->m_info.bottom_pos = static_cast<BottomRelativePosition>((this->m_info.bottom_pos + 1) % (BottomRelativePosition::BOT_REL_POS_END));
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
break;
case '6':
this->m_info.subscreen_offset_algorithm = static_cast<OffsetAlgorithm>((this->m_info.subscreen_offset_algorithm + 1) % (OffsetAlgorithm::OFF_ALGO_END));
this->future_operations.call_screen_settings_update = true;
break;
case '7':
this->m_info.subscreen_attached_offset_algorithm = static_cast<OffsetAlgorithm>((this->m_info.subscreen_attached_offset_algorithm + 1) % (OffsetAlgorithm::OFF_ALGO_END));
this->future_operations.call_screen_settings_update = true;
break;
case '4':
this->m_info.total_offset_algorithm_x = static_cast<OffsetAlgorithm>((this->m_info.total_offset_algorithm_x + 1) % (OffsetAlgorithm::OFF_ALGO_END));
this->future_operations.call_screen_settings_update = true;
break;
case '5':
this->m_info.total_offset_algorithm_y = static_cast<OffsetAlgorithm>((this->m_info.total_offset_algorithm_y + 1) % (OffsetAlgorithm::OFF_ALGO_END));
this->future_operations.call_screen_settings_update = true;
break;
case 'y':
this->prepare_size_ratios(true, false);
this->future_operations.call_screen_settings_update = true;
break;
case 'u':
this->prepare_size_ratios(false, true);
this->future_operations.call_screen_settings_update = true;
break;
case '8':
this->m_info.top_rotation = (this->m_info.top_rotation + 270) % 360;
this->m_info.bot_rotation = (this->m_info.bot_rotation + 270) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case '9':
this->m_info.top_rotation = (this->m_info.top_rotation + 90) % 360;
this->m_info.bot_rotation = (this->m_info.bot_rotation + 90) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'h':
this->m_info.top_rotation = (this->m_info.top_rotation + 270) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'j':
this->m_info.top_rotation = (this->m_info.top_rotation + 90) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'k':
this->m_info.bot_rotation = (this->m_info.bot_rotation + 270) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'l':
this->m_info.bot_rotation = (this->m_info.bot_rotation + 90) % 360;
this->prepare_size_ratios(false, false);
this->future_operations.call_rotate = true;
break;
case 'r':
if(this->m_info.is_fullscreen)
break;
this->m_info.rounded_corners_fix = !this->m_info.rounded_corners_fix;
this->future_operations.call_screen_settings_update = true;
this->print_notification_on_off("Extra Padding", this->m_info.rounded_corners_fix);
break;
case '2':
if(this->m_stype == WindowScreen::ScreenType::BOTTOM)
break;
this->m_info.top_par = static_cast<ParCorrection>((this->m_info.top_par + 1) % (ParCorrection::PAR_END));
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
this->print_notification("Top PAR: " + par_width_names[this->m_info.top_par]);
break;
case '3':
if(this->m_stype == WindowScreen::ScreenType::TOP)
break;
this->m_info.bot_par = static_cast<ParCorrection>((this->m_info.bot_par + 1) % (ParCorrection::PAR_END));
this->prepare_size_ratios(false, false);
this->future_operations.call_screen_settings_update = true;
this->print_notification("Bottom PAR: " + par_width_names[this->m_info.bot_par]);
break;
case 'm':
audio_data->change_audio_mute();
break;
case ',':
audio_data->change_audio_volume(false);
break;
case '.':
audio_data->change_audio_volume(true);
break;
default:
case sf::Event::MouseMoved:
consumed = false;
break;
}
break;
case sf::Event::KeyPressed:
switch (event_data.code) {
case sf::Keyboard::F1:
case sf::Keyboard::F2:
case sf::Keyboard::F3:
case sf::Keyboard::F4:
this->m_prepare_load = event_data.code - sf::Keyboard::F1 + 1;
case sf::Event::MouseButtonPressed:
consumed = false;
break;
case sf::Keyboard::F5:
case sf::Keyboard::F6:
case sf::Keyboard::F7:
case sf::Keyboard::F8:
this->m_prepare_save = event_data.code - sf::Keyboard::F5 + 1;
case sf::Event::MouseButtonReleased:
consumed = false;
break;
case sf::Event::JoystickButtonPressed:
consumed = false;
break;
case sf::Event::JoystickMoved:
consumed = false;
break;
default:
consumed = false;
break;
}
break;
case sf::Event::MouseMoved:
consumed = false;
break;
case sf::Event::MouseButtonPressed:
consumed = false;
break;
case sf::Event::MouseButtonReleased:
consumed = false;
break;
case sf::Event::JoystickButtonPressed:
consumed = false;
break;
case sf::Event::JoystickMoved:
consumed = false;
break;
default:
consumed = false;
break;
}
return consumed;
}
@@ -442,20 +506,46 @@ void WindowScreen::poll() {
return;
continue;
}
switch(this->loaded_menu) {
case DEFAULT_MENU_TYPE:
if(this->loaded_menu != CONNECT_MENU_TYPE) {
if(this->main_poll(event_data))
continue;
break;
case CONNECT_MENU_TYPE:
if(this->connection_menu->poll(event_data)) {
if(this->check_connection_menu_result() != -1)
return;
continue;
}
break;
default:
break;
}
switch(this->loaded_menu) {
case DEFAULT_MENU_TYPE:
if(this->no_menu_poll(event_data))
continue;
break;
case CONNECT_MENU_TYPE:
if(this->connection_menu->poll(event_data)) {
if(this->check_connection_menu_result() != -1)
return;
continue;
}
break;
case MAIN_MENU_TYPE:
if(this->main_menu->poll(event_data)) {
switch(this->main_menu->selected_index) {
case MAIN_MENU_OPEN:
this->m_prepare_open = true;
break;
case MAIN_MENU_CLOSE_MENU:
this->curr_menu = DEFAULT_MENU_TYPE;
return;
break;
case MAIN_MENU_QUIT_APPLICATION:
this->m_prepare_quit = true;
this->curr_menu = DEFAULT_MENU_TYPE;
return;
break;
default:
break;
}
this->main_menu->selected_index = MAIN_MENU_NO_ACTION;
continue;
}
break;
default:
break;
}
}
}
@@ -512,7 +602,7 @@ void WindowScreen::draw(double frame_time, VideoOutputData* out_buf) {
return;
bool should_be_open = this->display_data->split;
if(this->m_stype == WindowScreen::ScreenType::JOINT)
if(this->m_stype == ScreenType::JOINT)
should_be_open = !should_be_open;
if(this->m_win.isOpen() ^ should_be_open) {
if(this->m_win.isOpen())
@@ -520,7 +610,7 @@ void WindowScreen::draw(double frame_time, VideoOutputData* out_buf) {
else
this->open();
}
this->loaded_menu = this->display_data->curr_menu;
this->loaded_menu = this->curr_menu;
loaded_operations = future_operations;
if(this->m_win.isOpen() || this->loaded_operations.call_create) {
WindowScreen::reset_operations(future_operations);
@@ -543,6 +633,9 @@ void WindowScreen::draw(double frame_time, VideoOutputData* out_buf) {
case CONNECT_MENU_TYPE:
this->connection_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y);
break;
case MAIN_MENU_TYPE:
this->main_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, &this->loaded_info, this->capture_status->connected);
break;
default:
break;
}
@@ -560,7 +653,8 @@ void WindowScreen::draw(double frame_time, VideoOutputData* out_buf) {
}
void WindowScreen::setup_connection_menu(DevicesList *devices_list) {
this->display_data->curr_menu = CONNECT_MENU_TYPE;
this->curr_menu = CONNECT_MENU_TYPE;
this->connection_menu->reset_data();
this->connection_menu->insert_data(devices_list);
}
@@ -569,7 +663,7 @@ int WindowScreen::check_connection_menu_result() {
}
void WindowScreen::end_connection_menu() {
this->display_data->curr_menu = DEFAULT_MENU_TYPE;
this->curr_menu = DEFAULT_MENU_TYPE;
}
void WindowScreen::update_connection() {
@@ -666,21 +760,7 @@ void WindowScreen::print_notification_on_off(std::string base_text, bool value)
}
void WindowScreen::print_notification_float(std::string base_text, float value, int decimals) {
float approx_factor = pow(0.1, decimals) * (0.5);
int int_part = (int)(value + approx_factor);
int dec_part = (int)((value + approx_factor - int_part) * pow(10, decimals));
std::string status_text = std::to_string(int_part);
if(decimals > 0) {
if(!dec_part) {
status_text += ".";
for(int i = 0; i < decimals; i++)
status_text += "0";
}
else
status_text += "." + std::to_string(dec_part);
}
this->print_notification(base_text + ": " + status_text);
this->print_notification(base_text + ": " + get_float_str_decimals(value, decimals));
}
void WindowScreen::poll_window() {
@@ -791,16 +871,16 @@ std::string WindowScreen::title_factory() {
}
void WindowScreen::pre_texture_conversion_processing() {
if(this->loaded_menu != DEFAULT_MENU_TYPE)
if(this->loaded_menu == CONNECT_MENU_TYPE)
return;
//Place preprocessing window-specific effects here
this->in_tex.update((uint8_t*)this->saved_buf, IN_VIDEO_WIDTH, IN_VIDEO_HEIGHT, 0, 0);
}
void WindowScreen::post_texture_conversion_processing(out_rect_data &rect_data, const sf::RectangleShape &in_rect, bool actually_draw, bool is_top) {
if((is_top && this->m_stype == WindowScreen::ScreenType::BOTTOM) || ((!is_top) && this->m_stype == WindowScreen::ScreenType::TOP))
if((is_top && this->m_stype == ScreenType::BOTTOM) || ((!is_top) && this->m_stype == ScreenType::TOP))
return;
if(this->loaded_menu != DEFAULT_MENU_TYPE)
if(this->loaded_menu == CONNECT_MENU_TYPE)
return;
rect_data.out_tex.clear();
@@ -821,18 +901,21 @@ void WindowScreen::display_data_to_window(bool actually_draw) {
this->m_win.clear();
this->window_bg_processing();
switch(this->loaded_menu) {
case DEFAULT_MENU_TYPE:
if(this->m_stype != WindowScreen::ScreenType::BOTTOM)
if(this->loaded_menu != CONNECT_MENU_TYPE) {
if(this->m_stype != ScreenType::BOTTOM)
this->m_win.draw(this->m_out_rect_top.out_rect);
if(this->m_stype != WindowScreen::ScreenType::TOP)
if(this->m_stype != ScreenType::TOP)
this->m_win.draw(this->m_out_rect_bot.out_rect);
break;
case CONNECT_MENU_TYPE:
this->connection_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win);
break;
default:
break;
}
switch(this->loaded_menu) {
case CONNECT_MENU_TYPE:
this->connection_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win);
break;
case MAIN_MENU_TYPE:
this->main_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win);
break;
default:
break;
}
this->notification->draw(this->m_win);
this->m_win.display();
@@ -888,9 +971,9 @@ void WindowScreen::set_position_screens(sf::Vector2f &curr_top_screen_size, sf::
bot_screen_height = curr_bot_screen_size.x;
}
if(this->m_stype == WindowScreen::ScreenType::TOP)
if(this->m_stype == ScreenType::TOP)
bot_screen_width = bot_screen_height = 0;
if(this->m_stype == WindowScreen::ScreenType::BOTTOM)
if(this->m_stype == ScreenType::BOTTOM)
top_screen_width = top_screen_height = 0;
int greatest_width = top_screen_width;
@@ -900,7 +983,7 @@ void WindowScreen::set_position_screens(sf::Vector2f &curr_top_screen_size, sf::
if(greatest_height < bot_screen_height)
greatest_height = bot_screen_height;
if(this->m_stype == WindowScreen::ScreenType::JOINT) {
if(this->m_stype == ScreenType::JOINT) {
switch(this->loaded_info.bottom_pos) {
case UNDER_TOP:
bot_screen_x = apply_offset_algo(greatest_width - bot_screen_width, this->loaded_info.subscreen_offset_algorithm);
@@ -1002,7 +1085,7 @@ void WindowScreen::calc_scaling_resize_screens(sf::Vector2f &own_screen_size, sf
int own_width = own_screen_size.x;
get_par_size(own_width, own_height, own_scaling, own_par);
other_scaling = prepare_screen_ratio(other_screen_size, other_rotation, own_width, own_height, own_rotation, other_par);
if(this->m_stype == WindowScreen::ScreenType::JOINT) {
if(this->m_stype == ScreenType::JOINT) {
// Due to size differences, it may be possible that
// the chosen screen might be able to increase its
// scaling even more without compromising the other one...
@@ -1020,11 +1103,11 @@ void WindowScreen::prepare_size_ratios(bool top_increase, bool bot_increase) {
sf::Vector2f top_screen_size = getShownScreenSize(true, this->m_info.crop_kind);
sf::Vector2f bot_screen_size = getShownScreenSize(false, this->m_info.crop_kind);
if(this->m_stype == WindowScreen::ScreenType::TOP) {
if(this->m_stype == ScreenType::TOP) {
bot_increase = true;
top_increase = false;
}
if(this->m_stype == WindowScreen::ScreenType::BOTTOM) {
if(this->m_stype == ScreenType::BOTTOM) {
bot_increase = false;
top_increase = true;
}
@@ -1035,9 +1118,9 @@ void WindowScreen::prepare_size_ratios(bool top_increase, bool bot_increase) {
}
bool prioritize_top = (!bot_increase) && (top_increase || (this->m_info.bottom_pos == UNDER_TOP) || (this->m_info.bottom_pos == RIGHT_TOP));
if(prioritize_top)
calc_scaling_resize_screens(top_screen_size, bot_screen_size, this->m_info.top_scaling, this->m_info.bot_scaling, this->m_info.top_rotation, this->m_info.bot_rotation, top_increase, try_mantain_ratio, this->m_stype == WindowScreen::ScreenType::BOTTOM, this->m_info.top_par, this->m_info.bot_par);
calc_scaling_resize_screens(top_screen_size, bot_screen_size, this->m_info.top_scaling, this->m_info.bot_scaling, this->m_info.top_rotation, this->m_info.bot_rotation, top_increase, try_mantain_ratio, this->m_stype == ScreenType::BOTTOM, this->m_info.top_par, this->m_info.bot_par);
else
calc_scaling_resize_screens(bot_screen_size, top_screen_size, this->m_info.bot_scaling, this->m_info.top_scaling, this->m_info.bot_rotation, this->m_info.top_rotation, bot_increase, try_mantain_ratio, this->m_stype == WindowScreen::ScreenType::TOP, this->m_info.bot_par, this->m_info.top_par);
calc_scaling_resize_screens(bot_screen_size, top_screen_size, this->m_info.bot_scaling, this->m_info.top_scaling, this->m_info.bot_rotation, this->m_info.top_rotation, bot_increase, try_mantain_ratio, this->m_stype == ScreenType::TOP, this->m_info.bot_par, this->m_info.top_par);
}
int WindowScreen::get_fullscreen_offset_x(int top_width, int top_height, int bot_width, int bot_height) {

View File

@@ -218,9 +218,9 @@ static void mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data
curr_fps_array = new double[FPS_WINDOW_SIZE];
memset(out_buf, 0, sizeof(VideoOutputData));
WindowScreen top_screen(WindowScreen::ScreenType::TOP, &capture_data->status, &frontend_data.display_data, audio_data, &events_access);
WindowScreen bot_screen(WindowScreen::ScreenType::BOTTOM, &capture_data->status, &frontend_data.display_data, audio_data, &events_access);
WindowScreen joint_screen(WindowScreen::ScreenType::JOINT, &capture_data->status, &frontend_data.display_data, audio_data, &events_access);
WindowScreen top_screen(ScreenType::TOP, &capture_data->status, &frontend_data.display_data, audio_data, &events_access);
WindowScreen bot_screen(ScreenType::BOTTOM, &capture_data->status, &frontend_data.display_data, audio_data, &events_access);
WindowScreen joint_screen(ScreenType::JOINT, &capture_data->status, &frontend_data.display_data, audio_data, &events_access);
frontend_data.top_screen = &top_screen;
frontend_data.bot_screen = &bot_screen;
frontend_data.joint_screen = &joint_screen;

View File

@@ -227,6 +227,8 @@ JoystickAction get_joystick_action(uint32_t joystickId, uint32_t joy_button) {
return JOY_ACTION_CONFIRM;
if((joy_button == 2) || (joy_button == 3))
return JOY_ACTION_NEGATE;
if((joy_button == 4) || (joy_button == 5))
return JOY_ACTION_MENU;
return JOY_ACTION_NONE;
}

View File

@@ -4,6 +4,7 @@
#include <condition_variable>
#include <chrono>
#include <queue>
#include <cmath>
bool is_big_endian(void) {
union {
@@ -14,6 +15,24 @@ bool is_big_endian(void) {
return value.c[0] == 1;
}
std::string get_float_str_decimals(float value, int decimals) {
float approx_factor = pow(0.1, decimals) * (0.5);
int int_part = (int)(value + approx_factor);
int dec_part = (int)((value + approx_factor - int_part) * pow(10, decimals));
std::string return_text = std::to_string(int_part);
if(decimals > 0) {
if(!dec_part) {
return_text += ".";
for(int i = 0; i < decimals; i++)
return_text += "0";
}
else
return_text += "." + std::to_string(dec_part);
}
return return_text;
}
//============================================================================
ConsumerMutex::ConsumerMutex() {