| 844 | } |
| 845 | |
| 846 | void FullscreenUI::DrawFloatSpinBoxSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section, |
| 847 | const char* key, float default_value, float min_value, float max_value, float step_value, float multiplier, const char* format, |
| 848 | bool enabled, float height, std::pair<ImFont*, float> font, std::pair<ImFont*, float> summary_font) |
| 849 | { |
| 850 | const bool game_settings = IsEditingGameSettings(bsi); |
| 851 | const std::optional<float> value = |
| 852 | bsi->GetOptionalFloatValue(section, key, game_settings ? std::nullopt : std::optional<int>(default_value)); |
| 853 | const SmallString value_text = |
| 854 | value.has_value() ? SmallString::from_sprintf(format, value.value() * multiplier) : SmallString(FSUI_VSTR("Use Global Setting")); |
| 855 | |
| 856 | static bool manual_input = false; |
| 857 | |
| 858 | if (MenuButtonWithValue(title, summary, value_text.c_str(), enabled, height, font, summary_font)) |
| 859 | { |
| 860 | ImGui::OpenPopup(title); |
| 861 | manual_input = false; |
| 862 | } |
| 863 | |
| 864 | ImGui::SetNextWindowSize(LayoutScale(500.0f, 192.0f)); |
| 865 | ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); |
| 866 | |
| 867 | ImGui::PushFont(g_large_font.first, g_large_font.second); |
| 868 | ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); |
| 869 | ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); |
| 870 | ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); |
| 871 | ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, |
| 872 | LayoutScale(ImGuiFullscreen::LAYOUT_MENU_BUTTON_X_PADDING, ImGuiFullscreen::LAYOUT_MENU_BUTTON_Y_PADDING)); |
| 873 | |
| 874 | bool is_open = true; |
| 875 | if (ImGui::BeginPopupModal(title, &is_open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove)) |
| 876 | { |
| 877 | BeginMenuButtons(); |
| 878 | |
| 879 | float dlg_value = value.value_or(default_value) * multiplier; |
| 880 | bool dlg_value_changed = false; |
| 881 | |
| 882 | char str_value[32]; |
| 883 | std::snprintf(str_value, std::size(str_value), format, dlg_value); |
| 884 | |
| 885 | if (manual_input) |
| 886 | { |
| 887 | const float end = ImGui::GetCurrentWindow()->WorkRect.GetWidth(); |
| 888 | ImGui::SetNextItemWidth(end); |
| 889 | |
| 890 | // round trip to drop any suffixes (e.g. percent) |
| 891 | if (auto tmp_value = StringUtil::FromChars<float>(str_value); tmp_value.has_value()) |
| 892 | { |
| 893 | std::snprintf(str_value, std::size(str_value), |
| 894 | ((tmp_value.value() - std::floor(tmp_value.value())) < 0.01f) ? "%.0f" : "%f", tmp_value.value()); |
| 895 | } |
| 896 | |
| 897 | ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); |
| 898 | ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(12.0f, 10.0f)); |
| 899 | ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.2f, 0.2f, 0.2f, 1.0f)); |
| 900 | ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.25f, 0.25f, 0.25f, 1.0f)); |
| 901 | ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.3f, 0.3f, 0.3f, 1.0f)); |
| 902 | ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); |
| 903 |
nothing calls this directly
no test coverage detected