#ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif #pragma once #include #include #include #include #include #define GLFW_EXPOSE_NATIVE_WIN32 #include #include #include "imgui_internal.h" #include #include #include #include "firmware_update.h" #include "error_logging.h" #include "tex_loader.h" #include "gif_player.h" #include #include #include "model_download_manager.h" #include "steamvr_watch.h" #define WM_SYSTRAY_MENU WM_APP enum class Crash_Log_State { Begin, WaitingMemoryDump, Done }; enum class Refresh_Rate { _75hz, _90hz, _72hz }; enum class SteamVR_Warned_Settings { MotionSmoothing, SuperSampleValue, SuperSampleAuto, DisplayIdle, PauseVR, GPUProfiling, GPUBusMonitoring }; enum class Page_Type { Home, Advanced, VRSettings, ETSettings, DFRHome }; enum class Warning_State { None, SteamVR, PartialUpdate, NoCamera, UsingCPU, CameraRevoked, ModelFailure, NoFrustum, }; enum class Locales { None, En, Jp, Max }; enum class Auth_Code { InvalidToken, ExpiredToken, Success }; struct SteamVR_Flagged_Setting { std::string title; // User-friendly name (often the same name seen in the SteamVR settings window) std::string description; // User-friendly description of the setting and the potential issue that comes with it std::string json_category; // The json category containing the setting std::string steamvr_setting; // The setting name which is used in the JSON std::string steamvr_flag_value; // Intended value to look for, or the number threshold that the setting is greater than (or less than which is determined below) bool number_value_greater; // Check if greater, otherwise check less than bool check_absence; // Flag the setting if it does not exist in the SteamVR settings. This would mean the default value is problematic }; struct DFR_App { std::string title; std::string desc; }; struct Warning_Banner { std::string title; std::string button_text; }; struct Lang_Setting { std::string flag_path; std::string font_path; int font_size; int header_size; }; struct ET_Subscriber { std::string Label; std::string ID; std::string Tooltip; bool IsButton; std::function Get; std::function Set; }; struct ET_AdvToggle { std::string ID; std::function Get; std::function Set; }; struct ET_AdvSettingGroup { std::string Label; std::vector Toggles; }; struct ET_AdvSettingInput { std::string Label; std::string Desc; int FieldWidth; std::function Get; std::function Set; }; struct ET_AdvSettingDropdown { std::string Label; std::string Desc; std::vector Options; std::function Get; std::function Set; }; struct DFR_AdvSettingInput { std::string Label; std::string Desc; int FieldWidth; std::function Get; std::function Set; }; enum class Models_Filter { RemoteModels, OfflineModels, All }; enum class ET_AppsSection { Running, Selected }; struct AppListTab { const char* label; ET_AppsSection section; }; struct ET_ModelFilterGroup { std::string Label; Models_Filter Filter; }; struct G_DPI { float scale = 1.0f; // default 100% // Scale a size ImVec2 Vec2(float x, float y) const { return ImVec2(x * scale, y * scale); } // Scale a square ImVec2 Vec2(float size) const { return ImVec2(size * scale, size * scale); } // Scale a single float float F(float v) const { return v * scale; } // Update scale (e.g., on startup or DPI change) void Set(float s) { scale = s; } }; struct UI_Constants { const int brightness_min = -20; const int brightness_max = 100; const int overdrive_brightness_min = 101; const int overdrive_brightness_max = 150; const int fan_speed_min = 40; const int fan_speed_max = 100; const int ipd_min = 48; const int ipd_max = 75; const int prox_min = -500; const int prox_max = 500; const float control_padding = 180; const float control_thickness = 6; const std::vector et_notify_processes = { "VRChat.exe", "Resonite.exe", "FlightSimulator.exe" }; // Beyond theme colors const ImVec4 button_fill = ImVec4(1, 1, 1, 1); const ImVec4 button_hover = ImVec4(0.9f, 0.9f, 0.9f, 1); const ImVec4 button_click = ImVec4(0.7f, 0.7f, 0.7f, 1); const ImVec4 button_text = ImVec4(0, 0, 0, 1); const ImVec4 grey_button_fill = ImVec4(0.08f, 0.08f, 0.08f, 1); const ImVec4 grey_button_hover = grey_button_fill; const ImVec4 grey_button_click = ImVec4(0.14f, 0.14f, 0.14f, 1); const ImVec4 grey_button_text = ImVec4(1, 1, 1, 1); const ImVec4 button_fill_inactive = ImVec4(0.2f, 0.2f, 0.2f, 1); const ImVec4 button_hover_inactive = ImVec4(0.45f, 0.45f, 0.45f, 1); const ImVec4 button_click_inactive = ImVec4(0.3f, 0.3f, 0.3f, 1); const ImVec4 button_text_inactive = ImVec4(0.8f, 0.8f, 0.8f, 1); const ImVec4 checkbox_fill = ImVec4(0.401f, 0.217f, 1.68f, 1); const ImVec4 checkbox_hover = ImVec4(0.401f, 0.217f, 1.68f, 1); const ImVec4 checkbox_click = ImVec4(0.201f, 0.017f, 0.868f, 1); const ImVec4 checkbox_icon = ImVec4(1, 1, 1, 1); const ImVec4 textbox_fill = ImVec4(0.401f, 0.217f, 1.68f, 1); const ImVec4 textbox_active = ImVec4(0.501f, 0.317f, 1.78f, 1); const ImVec4 textbox_text = ImVec4(1, 1, 1, 1); const ImVec4 slider_fill = ImVec4(0.401f, 0.217f, 1.68f, 1); const ImVec4 slider_active = ImVec4(0.501f, 0.317f, 1.78f, 1); const ImVec4 slider_button = ImVec4(0.601f, 0.417f, 1.88f, 1); const ImVec4 slider_button_active = ImVec4(0.601f, 0.417f, 1.88f, 1); const ImVec4 dropdown_fill = ImVec4(0.401f, 0.217f, 1.68f, 1); const ImVec4 dropdown_hover = ImVec4(0.401f, 0.217f, 1.68f, 1); const ImVec4 dropdown_click = ImVec4(0.201f, 0.017f, 0.868f, 1); const ImVec4 dropdown_button = ImVec4(0.47f, 0.494f, 0.505f, 1); const ImVec4 dropdown_listing_hover = ImVec4(0.2863f, 0.5137f, 0.9843f, 1.0f); const ImVec4 dropdown_fill_inactive = ImVec4(0.239, 0.129, 0.600, 1.0); const ImVec4 dropdown_hover_inactive = ImVec4(0.239, 0.129, 0.600, 1.0); const ImVec4 dropdown_button_hover = ImVec4(0.37f, 0.394f, 0.405f, 1); const ImVec4 dropdown_button_click = ImVec4(0.37f, 0.394f, 0.405f, 1); const ImVec4 popup_title_color = ImVec4(0.401f, 0.217f, 1.68f, 1); const ImVec4 sub_text = ImVec4(0.47f, 0.494f, 0.505f, 1); const ImVec4 progress_fill = ImVec4(0.7f, 0.7f, 0.7f, 1); const ImVec4 hyperlink_text = ImVec4(0.2f, 0.6f, 1, 1); const int max_dfu_verification_checks = 4; const int model_check_interval = 15; // Check for new models every 15 seconds const int model_check_lifetime = 7200; // Checker loop only lasts 120 minutes if the flag is enabled // Eyetracking defaults // Smoothing filter default const float filter_default = 0.8f; // DFR defaults const std::string horizontal_focus_default = "0.6"; const std::string vertical_focus_default = "0.6"; const std::string peripheral_default = "0.4"; const std::string focus_default = "1"; const std::string transition_thickness_default = "0.3"; const int debug_gaze_default = 0; const float et_checkbox_Scale = 1.5f; const float et_model_ui_Scale = 1.5f; const float et_area_scale = 0.85f; const std::string agreement_link = "https://www.bigscreenvr.com/enrollprivacy"; const std::string quadviews_link = "https://github.com/mbucchia/Quad-Views-Foveated/wiki#setup"; const std::string mail_link = "mailto:support@bigscreenvr.com"; const ImVec2 alignment_gif_size = ImVec2(380, 260); const ImVec2 verify_gif_size = ImVec2(490, 322); const int fan_sample_speed = 70; // Predetermined RPM targets for the fan running at 70% const std::map fan_gen_targets = { {1, 7600}, {2, 9400} // gen2 is higher rpm }; }; inline UI_Constants UIConstants; // Stack saved variables in the ::run() method // Easy to pass a ref to this struct when calling // ui subfunctions rather than a loooong list of args struct UI_Run_State { firmware_update fw; Page_Type current_page = Page_Type::Home; Warning_State active_warning; std::string pending_popup; // Some default strings std::wstring steamvr_path = L"C:\\Program Files (x86)\\Steam\\steamapps\\common\\SteamVR"; std::wstring steamvr_settings_file; std::wstring steam_config_path; std::wstring exe_path; std::wstring settings_path = L"beyond_settings.json"; std::wstring firmware_contents_path = L"latest.beyondfw"; std::wstring dfu_firmware_path = L"eyetracking_firm.dfu"; std::wstring config_memory_backup_path = L"headset_memory_backup"; std::wstring lighthouse_restore_path = L""; std::wstring memory_restore_path = L""; Refresh_Rate current_refresh_rate = Refresh_Rate::_75hz; const std::map< Refresh_Rate, std::string> refresh_rates = { {Refresh_Rate::_75hz, "75hz"}, {Refresh_Rate::_90hz, "90hz"}, {Refresh_Rate::_72hz, "72hz"} }; float color[3] = { 0.0f, 0.0f, 1.0f }; // RGB LED color int slider_brightness = 100; int brightness = 100; // OLED display brightness (normal mode) int overdrive_brightness = 125; // OLED display brightness (in overdrive mode) float overdrive_split_pos = 200.0f; // initial guess at slider width. will be corrected on 2nd displayed frame of UI run int fan_speed = 80; int adjusted_ipd = 64; int applied_ipd = 64; int prox_offset = 0; bool vxr_auto_off = false; bool overdrive = false; bool launching_bootloader = false; bool opened_folder_select = false; std::wstring error_log_file_name; bool first_time_in_bootloader = true; bool first_time_in_crashhandler = true; Crash_Log_State cl_state = Crash_Log_State::Begin; int cl_mem_num = 0; bool firmware_update_requested = false; bool dfu_update_requested = false; bool valid_path = false; // wsteam_path leads to lighthouse_console.exe bool firmware_contents_exists = false; // firmware_contents_path ("latest.beyondfw") is on disk bool dfu_firmware_exists = false; bool checked_steamvr_settings = false; bool installed_et_driver = false; bool installed_bridge_driver = false; bool shown_bridge_driver_notice = false; bool has_eyetracking = false; bool ipd_supported = false; bool rebuild_fonts = false; bool token_input_changed = false; bool started_gif_animation = false; bool utility_failed_update = false; ImVec2 last_window_scale; uint64_t last_steamvr_check; uint64_t last_dpi_update; uint64_t last_et_firmware_check; uint64_t last_util_ver_check; uint64_t initiated_dfu_request; uint64_t model_check_timer; uint64_t model_lifetime_check_timer; std::vector hmd_serial_history; std::vector ignored_steamvr_warnings; std::vector flagged_settings; std::map hmd_fan_gen; std::vector ignored_utility_warnings; int rate_n = 0; // Used only in changing the refresh rate int dfu_check_count = 0; SteamVR_Warned_Settings staged_ignore_setting; char tint_r[5] = { 0 }; char tint_g[5] = { 0 }; char tint_b[5] = { 0 }; Locales active_locale = Locales::None; Auth_Code auth_status = Auth_Code::InvalidToken; // Eyetracking publishing settings (BU runtime) bool et_enabled = false; bool et_publish_memmap = true; bool et_publish_vrcft = false; bool et_publish_vrchat = false; bool et_publish_viewer = false; // Eyetracking behaviors bool et_smoothing_enabled = true; float et_smoothing_intensity = 0.8f; bool et_left_eye_enabled = true; bool et_right_eye_enabled = true; bool enabled_alignment_helper = false; bool seen_alignment_guide = false; bool dfr_settings_prompted = false; bool et_require_steamvr_presence = true; float et_flag_threshold = 0.5f; int et_blink_mode = 0; // Eyetracking states std::string et_model_path; std::string et_osc_ip = "127.0.0.1"; int et_osc_port = 9000; std::string et_selected_model; bool expecting_new_model = false; bool changed_DFR_setting = false; bool foundModelInProgress = false; bool rebuilding_Models = false; bool et_backported_settings = false; Models_Filter active_models_filter; ET_AppsSection et_current_apps_section = ET_AppsSection::Running; std::string pending_edit_model; std::string et_user_token; std::vector et_models; std::unordered_map et_labeled_models; std::vector et_removed_models; std::vector et_selected_apps; // Eyetracking DFR std::string quad_horizontal_focus_section = UIConstants.horizontal_focus_default; std::string quad_vertical_focus_section = UIConstants.vertical_focus_default; std::string quad_peripheral_multiplier = UIConstants.peripheral_default; std::string quad_focus_multiplier = UIConstants.focus_default; std::string quad_transition_thickness = UIConstants.transition_thickness_default; int quad_debug_gaze = UIConstants.debug_gaze_default; }; struct UI { const std::map languages = { {Locales::En, {"images/en.png", "fonts/HaasGrotDisp-55Roman.otf", 14, 25}}, {Locales::Jp, {"images/jp.png", "fonts/YuGothM.ttc", 15, 26}} }; std::map warned_settings; std::map warning_banners; std::vector DFR_apps; std::vector accuracy_tips; std::vector subscribers; std::vector et_adv_setting_toggles; std::vector et_adv_setting_inputs; std::vector et_adv_setting_dropdowns; std::vector dfr_setting_inputs; std::vector et_model_filters; std::vector et_app_list_tabs; void create_window(bool startClosed); void run(); void shutdown(); void load_fonts(); void localize_tables(); ImVec2 update_dpi(); bool close_existing_process(); bool bring_foreground(bool foreground_external); UI_Run_State* get_runtime_state(); // UI Sub-functions so we don't clutter run() void first_time_headset(UI_Run_State& rs); void show_steamvr_flagged_settings(UI_Run_State& rs); void show_home_page(UI_Run_State& rs); void show_advanced_settings(UI_Run_State& rs); void show_models(UI_Run_State& rs); void show_et_advanced_settings(UI_Run_State& rs); void show_eyetracking_settings(UI_Run_State& rs); void show_bootloader_menu(UI_Run_State& rs); void show_crashhandler_menu(UI_Run_State& rs); void show_DFR_home(UI_Run_State& rs); void DFR_quad_settings(UI_Run_State& rs, float popup_totalWidth); bool show_refresh_rate_buttons(UI_Run_State& rs); void show_dfu_menu(UI_Run_State& rs); void render_popups(UI_Run_State& rs); bool has_opened_eyetracking(); void update_models(std::vector newUserTrainedModels); std::atomic alive; std::atomic app_inactive; int window_width = 600; int window_height = 690; int pushed_styles = 0; const char* app_version = "0.0.0"; GLFWwindow* window = nullptr; std::atomic changing_refresh; std::atomic changing_ipd; std::atomic fetching_config; std::atomic finding_fan_gen; std::atomic uploading_lighthouse_config; std::atomic set_steamvr_settings; std::atomic set_current_refresh; std::atomic refresh_progress; std::atomic ipd_progress; std::atomic saving; std::atomic saving_progress; std::atomic reboot_after_save; std::string deviceType; Models_Filter models_filter; ImFont* font; ImFont* font_header; }; extern UI ui; extern G_DPI g_Dpi;