From 4c201994d421089493a7a996978e8239ad619a20 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 20 Aug 2020 11:21:15 +0200 Subject: [PATCH] DragFloat, DragScalar: Fixed ImGuiSliderFlags_ClampOnInput not being honored in the special case where v_min == v_max. (#3361) --- docs/CHANGELOG.txt | 3 ++ examples/example_win32_directx11/main.cpp | 5 ++ imgui_internal.h | 3 +- imgui_widgets.cpp | 58 +++++++++++++++++------ 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 40d65885..83ac4df7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -37,6 +37,9 @@ HOW TO UPDATE? Other Changes: +- DragFloat, DragScalar: Fixed ImGuiSliderFlags_ClampOnInput not being honored in the special case + where v_min == v_max. (#3361) + ----------------------------------------------------------------------- VERSION 1.78 (Released 2020-08-18) diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 310dc04a..d4920106 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -116,6 +116,11 @@ int main(int, char**) ImGui::Checkbox("Another Window", &show_another_window); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + + static float f2 = 0.0f; + ImGui::DragFloat("f2 limit", &f2, 1.0f, 0.0f, 100.0f, NULL, ImGuiSliderFlags_ClampOnInput); + ImGui::DragFloat("f2", &f2, 1.0f, 0.0f, 0.0f, NULL, ImGuiSliderFlags_ClampOnInput); + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) diff --git a/imgui_internal.h b/imgui_internal.h index 22ce4634..1e4384d0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1997,8 +1997,9 @@ namespace ImGui // Data type helpers IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format); - IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2); + IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2); IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format); + IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2); IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max); // InputText diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1a10a2e8..188bb882 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1758,7 +1758,7 @@ int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type return 0; } -void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2) +void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg1, const void* arg2) { IM_ASSERT(op == '+' || op == '-'); switch (data_type) @@ -1910,11 +1910,39 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b } template -static bool ClampBehaviorT(T* v, const T* v_min, const T* v_max) +static int DataTypeCompareT(const T* lhs, const T* rhs) { - // Clamp, both sides are optional + if (*lhs < *rhs) return -1; + if (*lhs > *rhs) return +1; + return 0; +} + +int ImGui::DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2) +{ + switch (data_type) + { + case ImGuiDataType_S8: return DataTypeCompareT((const ImS8* )arg_1, (const ImS8* )arg_2); + case ImGuiDataType_U8: return DataTypeCompareT((const ImU8* )arg_1, (const ImU8* )arg_2); + case ImGuiDataType_S16: return DataTypeCompareT((const ImS16* )arg_1, (const ImS16* )arg_2); + case ImGuiDataType_U16: return DataTypeCompareT((const ImU16* )arg_1, (const ImU16* )arg_2); + case ImGuiDataType_S32: return DataTypeCompareT((const ImS32* )arg_1, (const ImS32* )arg_2); + case ImGuiDataType_U32: return DataTypeCompareT((const ImU32* )arg_1, (const ImU32* )arg_2); + case ImGuiDataType_S64: return DataTypeCompareT((const ImS64* )arg_1, (const ImS64* )arg_2); + case ImGuiDataType_U64: return DataTypeCompareT((const ImU64* )arg_1, (const ImU64* )arg_2); + case ImGuiDataType_Float: return DataTypeCompareT((const float* )arg_1, (const float* )arg_2); + case ImGuiDataType_Double: return DataTypeCompareT((const double*)arg_1, (const double*)arg_2); + case ImGuiDataType_COUNT: break; + } + IM_ASSERT(0); + return 0; +} + +template +static bool DataTypeClampT(T* v, const T* v_min, const T* v_max) +{ + // Clamp, both sides are optional, return true if modified if (v_min && *v < *v_min) { *v = *v_min; return true; } - if (v_max && *v > *v_max) { *v = *v_max; return true; } + if (v_max && *v > * v_max) { *v = *v_max; return true; } return false; } @@ -1922,16 +1950,16 @@ bool ImGui::DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_m { switch (data_type) { - case ImGuiDataType_S8: return ClampBehaviorT((ImS8* )p_data, (const ImS8* )p_min, (const ImS8* )p_max); - case ImGuiDataType_U8: return ClampBehaviorT((ImU8* )p_data, (const ImU8* )p_min, (const ImU8* )p_max); - case ImGuiDataType_S16: return ClampBehaviorT((ImS16* )p_data, (const ImS16* )p_min, (const ImS16* )p_max); - case ImGuiDataType_U16: return ClampBehaviorT((ImU16* )p_data, (const ImU16* )p_min, (const ImU16* )p_max); - case ImGuiDataType_S32: return ClampBehaviorT((ImS32* )p_data, (const ImS32* )p_min, (const ImS32* )p_max); - case ImGuiDataType_U32: return ClampBehaviorT((ImU32* )p_data, (const ImU32* )p_min, (const ImU32* )p_max); - case ImGuiDataType_S64: return ClampBehaviorT((ImS64* )p_data, (const ImS64* )p_min, (const ImS64* )p_max); - case ImGuiDataType_U64: return ClampBehaviorT((ImU64* )p_data, (const ImU64* )p_min, (const ImU64* )p_max); - case ImGuiDataType_Float: return ClampBehaviorT((float* )p_data, (const float* )p_min, (const float* )p_max); - case ImGuiDataType_Double: return ClampBehaviorT((double*)p_data, (const double*)p_min, (const double*)p_max); + case ImGuiDataType_S8: return DataTypeClampT((ImS8* )p_data, (const ImS8* )p_min, (const ImS8* )p_max); + case ImGuiDataType_U8: return DataTypeClampT((ImU8* )p_data, (const ImU8* )p_min, (const ImU8* )p_max); + case ImGuiDataType_S16: return DataTypeClampT((ImS16* )p_data, (const ImS16* )p_min, (const ImS16* )p_max); + case ImGuiDataType_U16: return DataTypeClampT((ImU16* )p_data, (const ImU16* )p_min, (const ImU16* )p_max); + case ImGuiDataType_S32: return DataTypeClampT((ImS32* )p_data, (const ImS32* )p_min, (const ImS32* )p_max); + case ImGuiDataType_U32: return DataTypeClampT((ImU32* )p_data, (const ImU32* )p_min, (const ImU32* )p_max); + case ImGuiDataType_S64: return DataTypeClampT((ImS64* )p_data, (const ImS64* )p_min, (const ImS64* )p_max); + case ImGuiDataType_U64: return DataTypeClampT((ImU64* )p_data, (const ImU64* )p_min, (const ImU64* )p_max); + case ImGuiDataType_Float: return DataTypeClampT((float* )p_data, (const float* )p_min, (const float* )p_max); + case ImGuiDataType_Double: return DataTypeClampT((double*)p_data, (const double*)p_min, (const double*)p_max); case ImGuiDataType_COUNT: break; } IM_ASSERT(0); @@ -2201,7 +2229,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, if (temp_input_is_active) { // Only clamp CTRL+Click input when ImGuiSliderFlags_ClampInput is set - const bool is_clamp_input = (flags & ImGuiSliderFlags_ClampOnInput) != 0; + const bool is_clamp_input = (flags & ImGuiSliderFlags_ClampOnInput) != 0 && (p_min == NULL || p_max == NULL || DataTypeCompare(data_type, p_min, p_max) < 0); return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL); }