mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-11-03 17:24:24 +00:00 
			
		
		
		
	Removed support for legacy arithmetic operators (+*/) when inputing text into a slider/drag. (#4917, #3184)
This commit is contained in:
		@@ -1992,24 +1992,10 @@ void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const
 | 
			
		||||
 | 
			
		||||
// User can input math operators (e.g. +100) to edit a numerical values.
 | 
			
		||||
// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
 | 
			
		||||
bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format)
 | 
			
		||||
bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format)
 | 
			
		||||
{
 | 
			
		||||
    while (ImCharIsBlankA(*buf))
 | 
			
		||||
        buf++;
 | 
			
		||||
 | 
			
		||||
    // We don't support '-' op because it would conflict with inputing negative value.
 | 
			
		||||
    // Instead you can use +-100 to subtract from an existing value
 | 
			
		||||
    char op = buf[0];
 | 
			
		||||
    if (op == '+' || op == '*' || op == '/')
 | 
			
		||||
    {
 | 
			
		||||
        buf++;
 | 
			
		||||
        while (ImCharIsBlankA(*buf))
 | 
			
		||||
            buf++;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        op = 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (!buf[0])
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
@@ -2021,54 +2007,11 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
 | 
			
		||||
    if (format == NULL)
 | 
			
		||||
        format = type_info->ScanFmt;
 | 
			
		||||
 | 
			
		||||
    // FIXME-LEGACY: The aim is to remove those operators and write a proper expression evaluator at some point..
 | 
			
		||||
    int arg1i = 0;
 | 
			
		||||
    if (data_type == ImGuiDataType_S32)
 | 
			
		||||
    if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64 || data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
 | 
			
		||||
    {
 | 
			
		||||
        int* v = (int*)p_data;
 | 
			
		||||
        int arg0i = *v;
 | 
			
		||||
        float arg1f = 0.0f;
 | 
			
		||||
        if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
 | 
			
		||||
            return false;
 | 
			
		||||
        // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision
 | 
			
		||||
        if (op == '+')      { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); }                   // Add (use "+-" to subtract)
 | 
			
		||||
        else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); }                   // Multiply
 | 
			
		||||
        else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); }  // Divide
 | 
			
		||||
        else                { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; }                           // Assign constant
 | 
			
		||||
    }
 | 
			
		||||
    else if (data_type == ImGuiDataType_Float)
 | 
			
		||||
    {
 | 
			
		||||
        // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
 | 
			
		||||
        format = "%f";
 | 
			
		||||
        float* v = (float*)p_data;
 | 
			
		||||
        float arg0f = *v, arg1f = 0.0f;
 | 
			
		||||
        if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
 | 
			
		||||
            return false;
 | 
			
		||||
        if (sscanf(buf, format, &arg1f) < 1)
 | 
			
		||||
            return false;
 | 
			
		||||
        if (op == '+')      { *v = arg0f + arg1f; }                    // Add (use "+-" to subtract)
 | 
			
		||||
        else if (op == '*') { *v = arg0f * arg1f; }                    // Multiply
 | 
			
		||||
        else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
 | 
			
		||||
        else                { *v = arg1f; }                            // Assign constant
 | 
			
		||||
    }
 | 
			
		||||
    else if (data_type == ImGuiDataType_Double)
 | 
			
		||||
    {
 | 
			
		||||
        format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis
 | 
			
		||||
        double* v = (double*)p_data;
 | 
			
		||||
        double arg0f = *v, arg1f = 0.0;
 | 
			
		||||
        if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
 | 
			
		||||
            return false;
 | 
			
		||||
        if (sscanf(buf, format, &arg1f) < 1)
 | 
			
		||||
            return false;
 | 
			
		||||
        if (op == '+')      { *v = arg0f + arg1f; }                    // Add (use "+-" to subtract)
 | 
			
		||||
        else if (op == '*') { *v = arg0f * arg1f; }                    // Multiply
 | 
			
		||||
        else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
 | 
			
		||||
        else                { *v = arg1f; }                            // Assign constant
 | 
			
		||||
    }
 | 
			
		||||
    else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
 | 
			
		||||
    {
 | 
			
		||||
        // All other types assign constant
 | 
			
		||||
        // We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future.
 | 
			
		||||
        // For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
 | 
			
		||||
        if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
 | 
			
		||||
            format = type_info->ScanFmt;
 | 
			
		||||
        if (sscanf(buf, format, p_data) < 1)
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
@@ -3387,8 +3330,6 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
 | 
			
		||||
// However this may not be ideal for all uses, as some user code may break on out of bound values.
 | 
			
		||||
bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
 | 
			
		||||
    char fmt_buf[32];
 | 
			
		||||
    char data_buf[32];
 | 
			
		||||
    format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
 | 
			
		||||
@@ -3406,7 +3347,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
 | 
			
		||||
        memcpy(&data_backup, p_data, data_type_size);
 | 
			
		||||
 | 
			
		||||
        // Apply new value (or operations) then clamp
 | 
			
		||||
        DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL);
 | 
			
		||||
        DataTypeApplyFromText(data_buf, data_type, p_data, NULL);
 | 
			
		||||
        if (p_clamp_min || p_clamp_max)
 | 
			
		||||
        {
 | 
			
		||||
            if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
 | 
			
		||||
@@ -3453,7 +3394,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
 | 
			
		||||
        PushID(label);
 | 
			
		||||
        SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
 | 
			
		||||
        if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
 | 
			
		||||
            value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
 | 
			
		||||
            value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
 | 
			
		||||
 | 
			
		||||
        // Step buttons
 | 
			
		||||
        const ImVec2 backup_frame_padding = style.FramePadding;
 | 
			
		||||
@@ -3490,7 +3431,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
 | 
			
		||||
            value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
 | 
			
		||||
            value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
 | 
			
		||||
    }
 | 
			
		||||
    if (value_changed)
 | 
			
		||||
        MarkItemEdited(g.LastItemData.ID);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user