duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

imgui_fullscreen.h (16678B)


      1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0)
      3 
      4 #pragma once
      5 
      6 #include "common/types.h"
      7 
      8 #include "IconsFontAwesome5.h"
      9 #include "imgui.h"
     10 #include "imgui_internal.h"
     11 
     12 #include <functional>
     13 #include <memory>
     14 #include <optional>
     15 #include <span>
     16 #include <string>
     17 #include <string_view>
     18 #include <utility>
     19 #include <vector>
     20 
     21 class RGBA8Image;
     22 class GPUTexture;
     23 class SmallStringBase;
     24 
     25 namespace ImGuiFullscreen {
     26 #define HEX_TO_IMVEC4(hex, alpha)                                                                                      \
     27   ImVec4(static_cast<float>((hex >> 16) & 0xFFu) / 255.0f, static_cast<float>((hex >> 8) & 0xFFu) / 255.0f,            \
     28          static_cast<float>(hex & 0xFFu) / 255.0f, static_cast<float>(alpha) / 255.0f)
     29 
     30 static constexpr float LAYOUT_SCREEN_WIDTH = 1280.0f;
     31 static constexpr float LAYOUT_SCREEN_HEIGHT = 720.0f;
     32 static constexpr float LAYOUT_LARGE_FONT_SIZE = 26.0f;
     33 static constexpr float LAYOUT_MEDIUM_FONT_SIZE = 16.0f;
     34 static constexpr float LAYOUT_SMALL_FONT_SIZE = 10.0f;
     35 static constexpr float LAYOUT_MENU_BUTTON_HEIGHT = 50.0f;
     36 static constexpr float LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY = 26.0f;
     37 static constexpr float LAYOUT_MENU_BUTTON_X_PADDING = 15.0f;
     38 static constexpr float LAYOUT_MENU_BUTTON_Y_PADDING = 10.0f;
     39 static constexpr float LAYOUT_MENU_WINDOW_X_PADDING = 12.0f;
     40 static constexpr float LAYOUT_FOOTER_PADDING = 10.0f;
     41 static constexpr float LAYOUT_FOOTER_HEIGHT = LAYOUT_MEDIUM_FONT_SIZE + LAYOUT_FOOTER_PADDING * 2.0f;
     42 static constexpr float LAYOUT_HORIZONTAL_MENU_HEIGHT = 320.0f;
     43 static constexpr float LAYOUT_HORIZONTAL_MENU_PADDING = 30.0f;
     44 static constexpr float LAYOUT_HORIZONTAL_MENU_ITEM_WIDTH = 250.0f;
     45 
     46 extern ImFont* g_standard_font;
     47 extern ImFont* g_medium_font;
     48 extern ImFont* g_large_font;
     49 
     50 extern float g_layout_scale;
     51 extern float g_rcp_layout_scale;
     52 extern float g_layout_padding_left;
     53 extern float g_layout_padding_top;
     54 
     55 extern ImVec4 UIBackgroundColor;
     56 extern ImVec4 UIBackgroundTextColor;
     57 extern ImVec4 UIBackgroundLineColor;
     58 extern ImVec4 UIBackgroundHighlightColor;
     59 extern ImVec4 UIPopupBackgroundColor;
     60 extern ImVec4 UIDisabledColor;
     61 extern ImVec4 UIPrimaryColor;
     62 extern ImVec4 UIPrimaryLightColor;
     63 extern ImVec4 UIPrimaryDarkColor;
     64 extern ImVec4 UIPrimaryTextColor;
     65 extern ImVec4 UITextHighlightColor;
     66 extern ImVec4 UIPrimaryLineColor;
     67 extern ImVec4 UISecondaryColor;
     68 extern ImVec4 UISecondaryWeakColor; // Not currently used.
     69 extern ImVec4 UISecondaryStrongColor;
     70 extern ImVec4 UISecondaryTextColor;
     71 
     72 ALWAYS_INLINE static float LayoutScale(float v)
     73 {
     74   return ImCeil(g_layout_scale * v);
     75 }
     76 
     77 ALWAYS_INLINE static ImVec2 LayoutScale(const ImVec2& v)
     78 {
     79   return ImVec2(ImCeil(v.x * g_layout_scale), ImCeil(v.y * g_layout_scale));
     80 }
     81 
     82 ALWAYS_INLINE static ImVec2 LayoutScale(float x, float y)
     83 {
     84   return ImVec2(ImCeil(x * g_layout_scale), ImCeil(y * g_layout_scale));
     85 }
     86 
     87 ALWAYS_INLINE static float LayoutUnscale(float v)
     88 {
     89   return ImCeil(g_rcp_layout_scale * v);
     90 }
     91 ALWAYS_INLINE static ImVec2 LayoutUnscale(const ImVec2& v)
     92 {
     93   return ImVec2(ImCeil(v.x * g_rcp_layout_scale), ImCeil(v.y * g_rcp_layout_scale));
     94 }
     95 ALWAYS_INLINE static ImVec2 LayoutUnscale(float x, float y)
     96 {
     97   return ImVec2(ImCeil(x * g_rcp_layout_scale), ImCeil(y * g_rcp_layout_scale));
     98 }
     99 
    100 ALWAYS_INLINE static ImVec4 ModAlpha(const ImVec4& v, float a)
    101 {
    102   return ImVec4(v.x, v.y, v.z, a);
    103 }
    104 
    105 ALWAYS_INLINE static ImVec4 MulAlpha(const ImVec4& v, float a)
    106 {
    107   return ImVec4(v.x, v.y, v.z, v.w * a);
    108 }
    109 
    110 ALWAYS_INLINE static std::string_view RemoveHash(std::string_view s)
    111 {
    112   const std::string_view::size_type pos = s.find('#');
    113   return (pos != std::string_view::npos) ? s.substr(0, pos) : s;
    114 }
    115 
    116 /// Centers an image within the specified bounds, scaling up or down as needed.
    117 ImRect CenterImage(const ImVec2& fit_size, const ImVec2& image_size);
    118 ImRect CenterImage(const ImRect& fit_rect, const ImVec2& image_size);
    119 
    120 /// Initializes, setting up any state.
    121 bool Initialize(const char* placeholder_image_path);
    122 
    123 void SetTheme(bool light);
    124 void SetFonts(ImFont* standard_font, ImFont* medium_font, ImFont* large_font);
    125 bool UpdateLayoutScale();
    126 
    127 /// Shuts down, clearing all state.
    128 void Shutdown();
    129 
    130 /// Texture cache.
    131 const std::shared_ptr<GPUTexture>& GetPlaceholderTexture();
    132 std::unique_ptr<GPUTexture> CreateTextureFromImage(const RGBA8Image& image);
    133 std::shared_ptr<GPUTexture> LoadTexture(std::string_view path);
    134 GPUTexture* GetCachedTexture(std::string_view name);
    135 GPUTexture* GetCachedTextureAsync(std::string_view name);
    136 bool InvalidateCachedTexture(const std::string& path);
    137 void UploadAsyncTextures();
    138 
    139 void BeginLayout();
    140 void EndLayout();
    141 
    142 void PushResetLayout();
    143 void PopResetLayout();
    144 
    145 enum class FocusResetType : u8
    146 {
    147   None,
    148   PopupOpened,
    149   PopupClosed,
    150   ViewChanged,
    151   Other,
    152 };
    153 void QueueResetFocus(FocusResetType type);
    154 bool ResetFocusHere();
    155 bool IsFocusResetQueued();
    156 bool IsFocusResetFromWindowChange();
    157 FocusResetType GetQueuedFocusResetType();
    158 void ForceKeyNavEnabled();
    159 
    160 bool WantsToCloseMenu();
    161 void ResetCloseMenuIfNeeded();
    162 
    163 void PushPrimaryColor();
    164 void PopPrimaryColor();
    165 
    166 void DrawWindowTitle(const char* title);
    167 
    168 bool BeginFullscreenColumns(const char* title = nullptr, float pos_y = 0.0f, bool expand_to_screen_width = false,
    169                             bool footer = false);
    170 void EndFullscreenColumns();
    171 
    172 bool BeginFullscreenColumnWindow(float start, float end, const char* name,
    173                                  const ImVec4& background = UIBackgroundColor);
    174 void EndFullscreenColumnWindow();
    175 
    176 bool BeginFullscreenWindow(float left, float top, float width, float height, const char* name,
    177                            const ImVec4& background = HEX_TO_IMVEC4(0x212121, 0xFF), float rounding = 0.0f,
    178                            const ImVec2& padding = ImVec2(), ImGuiWindowFlags flags = 0);
    179 bool BeginFullscreenWindow(const ImVec2& position, const ImVec2& size, const char* name,
    180                            const ImVec4& background = HEX_TO_IMVEC4(0x212121, 0xFF), float rounding = 0.0f,
    181                            const ImVec2& padding = ImVec2(), ImGuiWindowFlags flags = 0);
    182 void EndFullscreenWindow();
    183 
    184 bool IsGamepadInputSource();
    185 void CreateFooterTextString(SmallStringBase& dest, std::span<const std::pair<const char*, std::string_view>> items);
    186 void SetFullscreenFooterText(std::string_view text);
    187 void SetFullscreenFooterText(std::span<const std::pair<const char*, std::string_view>> items);
    188 void DrawFullscreenFooter();
    189 
    190 void PrerenderMenuButtonBorder();
    191 void BeginMenuButtons(u32 num_items = 0, float y_align = 0.0f, float x_padding = LAYOUT_MENU_BUTTON_X_PADDING,
    192                       float y_padding = LAYOUT_MENU_BUTTON_Y_PADDING, float item_height = LAYOUT_MENU_BUTTON_HEIGHT);
    193 void EndMenuButtons();
    194 void GetMenuButtonFrameBounds(float height, ImVec2* pos, ImVec2* size);
    195 bool MenuButtonFrame(const char* str_id, bool enabled, float height, bool* visible, bool* hovered, ImVec2* min,
    196                      ImVec2* max, ImGuiButtonFlags flags = 0, float hover_alpha = 1.0f);
    197 void DrawMenuButtonFrame(const ImVec2& p_min, const ImVec2& p_max, ImU32 fill_col, bool border = true,
    198                          float rounding = 0.0f);
    199 void ResetMenuButtonFrame();
    200 void MenuHeading(const char* title, bool draw_line = true);
    201 bool MenuHeadingButton(const char* title, const char* value = nullptr, bool enabled = true, bool draw_line = true);
    202 bool ActiveButton(const char* title, bool is_active, bool enabled = true,
    203                   float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font);
    204 bool DefaultActiveButton(const char* title, bool is_active, bool enabled = true,
    205                          float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font);
    206 bool ActiveButtonWithRightText(const char* title, const char* right_title, bool is_active, bool enabled = true,
    207                                float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font);
    208 bool MenuButton(const char* title, const char* summary, bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
    209                 ImFont* font = g_large_font, ImFont* summary_font = g_medium_font);
    210 bool MenuButtonWithoutSummary(const char* title, bool enabled = true,
    211                               float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font,
    212                               const ImVec2& text_align = ImVec2(0.0f, 0.0f));
    213 bool MenuButtonWithValue(const char* title, const char* summary, const char* value, bool enabled = true,
    214                          float height = LAYOUT_MENU_BUTTON_HEIGHT, ImFont* font = g_large_font,
    215                          ImFont* summary_font = g_medium_font);
    216 bool MenuImageButton(const char* title, const char* summary, ImTextureID user_texture_id, const ImVec2& image_size,
    217                      bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
    218                      const ImVec2& uv0 = ImVec2(0.0f, 0.0f), const ImVec2& uv1 = ImVec2(1.0f, 1.0f),
    219                      ImFont* font = g_large_font, ImFont* summary_font = g_medium_font);
    220 bool FloatingButton(const char* text, float x, float y, float width = -1.0f,
    221                     float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, float anchor_x = 0.0f, float anchor_y = 0.0f,
    222                     bool enabled = true, ImFont* font = g_large_font, ImVec2* out_position = nullptr,
    223                     bool repeat_button = false);
    224 bool ToggleButton(const char* title, const char* summary, bool* v, bool enabled = true,
    225                   float height = LAYOUT_MENU_BUTTON_HEIGHT, ImFont* font = g_large_font,
    226                   ImFont* summary_font = g_medium_font);
    227 bool ThreeWayToggleButton(const char* title, const char* summary, std::optional<bool>* v, bool enabled = true,
    228                           float height = LAYOUT_MENU_BUTTON_HEIGHT, ImFont* font = g_large_font,
    229                           ImFont* summary_font = g_medium_font);
    230 bool RangeButton(const char* title, const char* summary, s32* value, s32 min, s32 max, s32 increment,
    231                  const char* format = "%d", bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
    232                  ImFont* font = g_large_font, ImFont* summary_font = g_medium_font, const char* ok_text = "OK");
    233 bool RangeButton(const char* title, const char* summary, float* value, float min, float max, float increment,
    234                  const char* format = "%f", bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
    235                  ImFont* font = g_large_font, ImFont* summary_font = g_medium_font, const char* ok_text = "OK");
    236 bool EnumChoiceButtonImpl(const char* title, const char* summary, s32* value_pointer,
    237                           const char* (*to_display_name_function)(s32 value, void* opaque), void* opaque, u32 count,
    238                           bool enabled, float height, ImFont* font, ImFont* summary_font);
    239 
    240 template<typename DataType, typename CountType>
    241 ALWAYS_INLINE static bool EnumChoiceButton(const char* title, const char* summary, DataType* value_pointer,
    242                                            const char* (*to_display_name_function)(DataType value), CountType count,
    243                                            bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
    244                                            ImFont* font = g_large_font, ImFont* summary_font = g_medium_font)
    245 {
    246   s32 value = static_cast<s32>(*value_pointer);
    247   auto to_display_name_wrapper = [](s32 value, void* opaque) -> const char* {
    248     return (*static_cast<decltype(to_display_name_function)*>(opaque))(static_cast<DataType>(value));
    249   };
    250 
    251   if (EnumChoiceButtonImpl(title, summary, &value, to_display_name_wrapper, &to_display_name_function,
    252                            static_cast<u32>(count), enabled, height, font, summary_font))
    253   {
    254     *value_pointer = static_cast<DataType>(value);
    255     return true;
    256   }
    257   else
    258   {
    259     return false;
    260   }
    261 }
    262 
    263 void DrawShadowedText(ImDrawList* dl, ImFont* font, const ImVec2& pos, u32 col, const char* text,
    264                       const char* text_end = nullptr, float wrap_width = 0.0f);
    265 
    266 void BeginNavBar(float x_padding = LAYOUT_MENU_BUTTON_X_PADDING, float y_padding = LAYOUT_MENU_BUTTON_Y_PADDING);
    267 void EndNavBar();
    268 void NavTitle(const char* title, float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font);
    269 void RightAlignNavButtons(u32 num_items = 0, float item_width = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY,
    270                           float item_height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
    271 bool NavButton(const char* title, bool is_active, bool enabled = true, float width = -1.0f,
    272                float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font);
    273 bool NavTab(const char* title, bool is_active, bool enabled, float width, float height, const ImVec4& background,
    274             ImFont* font = g_large_font);
    275 
    276 bool BeginHorizontalMenu(const char* name, const ImVec2& position, const ImVec2& size, u32 num_items);
    277 void EndHorizontalMenu();
    278 bool HorizontalMenuItem(GPUTexture* icon, const char* title, const char* description);
    279 
    280 using FileSelectorCallback = std::function<void(const std::string& path)>;
    281 using FileSelectorFilters = std::vector<std::string>;
    282 bool IsFileSelectorOpen();
    283 void OpenFileSelector(std::string_view title, bool select_directory, FileSelectorCallback callback,
    284                       FileSelectorFilters filters = FileSelectorFilters(),
    285                       std::string initial_directory = std::string());
    286 void CloseFileSelector();
    287 
    288 using ChoiceDialogCallback = std::function<void(s32 index, const std::string& title, bool checked)>;
    289 using ChoiceDialogOptions = std::vector<std::pair<std::string, bool>>;
    290 bool IsChoiceDialogOpen();
    291 void OpenChoiceDialog(std::string_view title, bool checkable, ChoiceDialogOptions options,
    292                       ChoiceDialogCallback callback);
    293 void CloseChoiceDialog();
    294 
    295 using InputStringDialogCallback = std::function<void(std::string text)>;
    296 bool IsInputDialogOpen();
    297 void OpenInputStringDialog(std::string title, std::string message, std::string caption, std::string ok_button_text,
    298                            InputStringDialogCallback callback);
    299 void CloseInputDialog();
    300 
    301 using ConfirmMessageDialogCallback = std::function<void(bool)>;
    302 using InfoMessageDialogCallback = std::function<void()>;
    303 using MessageDialogCallback = std::function<void(s32)>;
    304 bool IsMessageBoxDialogOpen();
    305 void OpenConfirmMessageDialog(std::string title, std::string message, ConfirmMessageDialogCallback callback,
    306                               std::string yes_button_text = ICON_FA_CHECK " Yes",
    307                               std::string no_button_text = ICON_FA_TIMES " No");
    308 void OpenInfoMessageDialog(std::string title, std::string message, InfoMessageDialogCallback callback = {},
    309                            std::string button_text = ICON_FA_WINDOW_CLOSE " Close");
    310 void OpenMessageDialog(std::string title, std::string message, MessageDialogCallback callback,
    311                        std::string first_button_text, std::string second_button_text, std::string third_button_text);
    312 void CloseMessageDialog();
    313 
    314 float GetNotificationVerticalPosition();
    315 float GetNotificationVerticalDirection();
    316 void SetNotificationVerticalPosition(float position, float direction);
    317 
    318 void OpenBackgroundProgressDialog(const char* str_id, std::string message, s32 min, s32 max, s32 value);
    319 void UpdateBackgroundProgressDialog(const char* str_id, std::string message, s32 min, s32 max, s32 value);
    320 void CloseBackgroundProgressDialog(const char* str_id);
    321 
    322 void AddNotification(std::string key, float duration, std::string title, std::string text, std::string image_path);
    323 void ClearNotifications();
    324 
    325 void ShowToast(std::string title, std::string message, float duration = 10.0f);
    326 void ClearToast();
    327 
    328 // Message callbacks.
    329 void GetChoiceDialogHelpText(SmallStringBase& dest);
    330 void GetFileSelectorHelpText(SmallStringBase& dest);
    331 void GetInputDialogHelpText(SmallStringBase& dest);
    332 } // namespace ImGuiFullscreen
    333 
    334 // Host UI triggers from Big Picture mode.
    335 namespace Host {
    336 /// Returns true if native file dialogs should be preferred over Big Picture.
    337 bool ShouldPreferHostFileSelector();
    338 
    339 /// Opens a file selector dialog.
    340 using FileSelectorCallback = std::function<void(const std::string& path)>;
    341 using FileSelectorFilters = std::vector<std::string>;
    342 void OpenHostFileSelectorAsync(std::string_view title, bool select_directory, FileSelectorCallback callback,
    343                                FileSelectorFilters filters = FileSelectorFilters(),
    344                                std::string_view initial_directory = std::string_view());
    345 } // namespace Host