From d7e24416dd2d8b0ff82dff433c89f04b961338cc Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Apr 2018 11:08:45 +0200 Subject: [PATCH] DragFloat/SliderFloat internal InputScalar relies on the user supplied format string to format and parse value. (#648) The trailing text after the format will be displayed in the InputText but not affect back parsing. Ideally we can try to strip it later. --- imgui.cpp | 49 +++++++++++++++++++----------------------------- imgui_internal.h | 15 ++++++++------- 2 files changed, 27 insertions(+), 37 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 86f51c08..78734d7c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -748,7 +748,6 @@ static int InputTextCalcTextLenAndLineCount(const char* text_begin, static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format); -static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, int decimal_precision); static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2); static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format); @@ -8454,30 +8453,6 @@ static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType da return 0; } -static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, int decimal_precision) -{ - if (decimal_precision < 0) - { - if (data_type == ImGuiDataType_Int) - return ImFormatString(buf, buf_size, "%d", *(const int*)data_ptr); - if (data_type == ImGuiDataType_Float) - return ImFormatString(buf, buf_size, "%f", *(const float*)data_ptr); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits? - if (data_type == ImGuiDataType_Double) - return ImFormatString(buf, buf_size, "%f", *(const double*)data_ptr); - } - else - { - if (data_type == ImGuiDataType_Int) - return ImFormatString(buf, buf_size, "%.*d", decimal_precision, *(const int*)data_ptr); - if (data_type == ImGuiDataType_Float) - return ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(const float*)data_ptr); - if (data_type == ImGuiDataType_Double) - return ImFormatString(buf, buf_size, "%.*g", decimal_precision, *(const double*)data_ptr); - } - IM_ASSERT(0); - return 0; -} - static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2) { IM_ASSERT(op == '+' || op == '-'); @@ -8582,7 +8557,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b // Create text input in place of a slider (when CTRL+Clicking on slider) // FIXME: Logic is messy and confusing. -bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision) +bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -8595,9 +8570,10 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label FocusableItemUnregister(window); char buf[32]; - DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, decimal_precision); + format = ParseFormatSkipLeadingText(format); + DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, format); ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal); - bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), flags); + bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), bb.GetSize(), flags); if (g.ScalarAsInputTextId == 0) // First frame we started displaying the InputText widget { IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) @@ -8609,6 +8585,19 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label return false; } +const char* ImGui::ParseFormatSkipLeadingText(const char* fmt) +{ + if (fmt[0] == '%') + return fmt; + while (char c = fmt[0]) + { + if (c == '%' && fmt[1] != '%') + return fmt; + fmt++; + } + return fmt; +} + // Parse display precision back from the display format string int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) { @@ -8880,7 +8869,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c } } if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) - return InputScalarAsWidgetReplacement(frame_bb, label, ImGuiDataType_Float, v, id, decimal_precision); + return InputScalarAsWidgetReplacement(frame_bb, id, label, ImGuiDataType_Float, v, format); // Actual slider behavior + render grab ItemSize(total_bb, style.FramePadding.y); @@ -9189,7 +9178,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f } } if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id)) - return InputScalarAsWidgetReplacement(frame_bb, label, ImGuiDataType_Float, v, id, decimal_precision); + return InputScalarAsWidgetReplacement(frame_bb, id, label, ImGuiDataType_Float, v, format); // Actual drag behavior ItemSize(total_bb, style.FramePadding.y); diff --git a/imgui_internal.h b/imgui_internal.h index 617527fc..548d7729 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1097,18 +1097,18 @@ namespace ImGui IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius); IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0); - IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power); - IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* display_format); + IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* format, float power); + IMGUI_API bool SliderIntN(const char* label, int* v, int components, int v_min, int v_max, const char* format); IMGUI_API bool DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_speed, float v_min, float v_max, int decimal_precision, float power); - IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* display_format, float power); - IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* display_format); + IMGUI_API bool DragFloatN(const char* label, float* v, int components, float v_speed, float v_min, float v_max, const char* format, float power); + IMGUI_API bool DragIntN(const char* label, int* v, int components, float v_speed, int v_min, int v_max, const char* format); IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputFloatN(const char* label, float* v, int components, const char* format, ImGuiInputTextFlags extra_flags); IMGUI_API bool InputIntN(const char* label, int* v, int components, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags); - IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision); + IMGUI_API bool InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* format, ImGuiInputTextFlags extra_flags); + IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format); IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags); @@ -1119,7 +1119,8 @@ namespace ImGui IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size); - IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value); + IMGUI_API const char* ParseFormatSkipLeadingText(const char* format); + IMGUI_API int ParseFormatPrecision(const char* format, int default_value); IMGUI_API float RoundScalar(float value, int decimal_precision); // Shade functions (write over already created vertices)