389
389
- input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
390
390
- input text multi-line: way to dynamically grow the buffer without forcing the user to initially allocate for worse case (follow up on #200)
391
391
- input text multi-line: line numbers? status bar? (follow up on #200)
392
- !- input number: large int not reliably supported because of int<>float conversions.
393
392
- input number: optional range min/max for Input*() functions
394
393
- input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
395
394
- input number: use mouse wheel to step up/down
@@ -5829,9 +5828,57 @@ ImGuiID ImGui::GetID(const void* ptr_id)
5829
5828
return GImGui->CurrentWindow->GetID(ptr_id);
5830
5829
}
5831
5830
5831
+ enum ImGuiDataType
5832
+ {
5833
+ ImGuiDataType_Int,
5834
+ ImGuiDataType_Float
5835
+ };
5836
+
5837
+ enum ImGuiDataTypeOp
5838
+ {
5839
+ ImGuiDataTypeOp_Add,
5840
+ ImGuiDataTypeOp_Sub
5841
+ };
5842
+
5843
+ static inline void DataTypeFormat(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size)
5844
+ {
5845
+ if (data_type == ImGuiDataType_Int)
5846
+ {
5847
+ if (decimal_precision < 0)
5848
+ ImFormatString(buf, buf_size, "%d", *(int*)data_ptr);
5849
+ else
5850
+ ImFormatString(buf, buf_size, "%.*d", decimal_precision, *(int*)data_ptr);
5851
+ }
5852
+ else if (data_type == ImGuiDataType_Float)
5853
+ {
5854
+ if (decimal_precision < 0)
5855
+ ImFormatString(buf, buf_size, "%f", *(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?
5856
+ else
5857
+ ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(float*)data_ptr);
5858
+ }
5859
+ }
5860
+
5861
+ static void DataTypeApplyOp(ImGuiDataType data_type, ImGuiDataTypeOp op, void* value1, const void* value2)// Store into value1
5862
+ {
5863
+ if (data_type == ImGuiDataType_Int)
5864
+ {
5865
+ if (op == ImGuiDataTypeOp_Add)
5866
+ *(int*)value1 = *(int*)value1 + *(const int*)value2;
5867
+ else if (op == ImGuiDataTypeOp_Sub)
5868
+ *(int*)value1 = *(int*)value1 - *(const int*)value2;
5869
+ }
5870
+ else if (data_type == ImGuiDataType_Float)
5871
+ {
5872
+ if (op == ImGuiDataTypeOp_Add)
5873
+ *(float*)value1 = *(float*)value1 + *(const float*)value2;
5874
+ else if (op == ImGuiDataTypeOp_Sub)
5875
+ *(float*)value1 = *(float*)value1 - *(const float*)value2;
5876
+ }
5877
+ }
5878
+
5832
5879
// User can input math operators (e.g. +100) to edit a numerical values.
5833
5880
// NB: only call right after InputText because we are using its InitialValue storage
5834
- static void InputTextApplyArithmeticOp (const char* buf, float *v )
5881
+ static void DataTypeApplyOpFromText (const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr )
5835
5882
{
5836
5883
while (ImCharIsSpace(*buf))
5837
5884
buf++;
@@ -5852,27 +5899,38 @@ static void InputTextApplyArithmeticOp(const char* buf, float *v)
5852
5899
if (!buf[0])
5853
5900
return;
5854
5901
5855
- float ref_v = *v;
5856
- if (op)
5857
- if (sscanf(GImGui->InputTextState.InitialText.begin(), "%f", &ref_v) < 1)
5858
- return;
5902
+ if (data_type == ImGuiDataType_Int)
5903
+ {
5904
+ int* v = (int*)data_ptr;
5905
+ int ref_v = *v;
5906
+ if (op && sscanf(initial_value_buf, "%d", &ref_v) < 1)
5907
+ return;
5859
5908
5860
- float op_v = 0.0f;
5861
- if (sscanf(buf, "%f", &op_v) < 1)
5862
- return;
5909
+ // Store operand in a double so we can store a big integer (e.g. 2000000003) reliably as well as fractional value for multipliers (*1.1)
5910
+ double op_v = 0.0f;
5911
+ if (sscanf(buf, "%lf", &op_v) < 1)
5912
+ return;
5863
5913
5864
- if (op == '+')
5865
- *v = ref_v + op_v; // add (uses "+-" to substract)
5866
- else if (op == '*')
5867
- *v = ref_v * op_v; // multiply
5868
- else if (op == '/')
5914
+ if (op == '+') { *v = (int)(ref_v + op_v); } // Add (use "+-" to subtract)
5915
+ else if (op == '*') { *v = (int)(ref_v * op_v); } // Multiply
5916
+ else if (op == '/') { if (op_v != 0.0f) *v = (int)(ref_v / op_v); } // Divide
5917
+ else { *v = (int)op_v; } // Assign constant
5918
+ }
5919
+ else if (data_type == ImGuiDataType_Float)
5869
5920
{
5870
- if (op_v == 0.0f) // divide
5921
+ float* v = (float*)data_ptr;
5922
+ float ref_v = *v;
5923
+ if (op && sscanf(initial_value_buf, "%f", &ref_v) < 1)
5924
+ return;
5925
+ float op_v = 0.0f;
5926
+ if (sscanf(buf, "%f", &op_v) < 1)
5871
5927
return;
5872
- *v = ref_v / op_v;
5928
+
5929
+ if (op == '+') { *v = ref_v + op_v; } // Add (use "+-" to subtract)
5930
+ else if (op == '*') { *v = ref_v * op_v; } // Multiply
5931
+ else if (op == '/') { if (op_v != 0.0f) *v = ref_v / op_v; } // Divide
5932
+ else { *v = op_v; } // Assign constant
5873
5933
}
5874
- else
5875
- *v = op_v; // Constant
5876
5934
}
5877
5935
5878
5936
// Create text input in place of a slider (when CTRL+Clicking on slider)
@@ -5904,9 +5962,7 @@ static bool InputFloatReplaceWidget(const ImRect& aabb, const char* label, float
5904
5962
g.ScalarAsInputTextId = 0;
5905
5963
}
5906
5964
if (value_changed)
5907
- {
5908
- InputTextApplyArithmeticOp(text_buf, v);
5909
- }
5965
+ DataTypeApplyOpFromText(text_buf, GImGui->InputTextState.InitialText.begin(), ImGuiDataType_Float, v);
5910
5966
return value_changed;
5911
5967
}
5912
5968
@@ -7608,7 +7664,7 @@ bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, co
7608
7664
return ret;
7609
7665
}
7610
7666
7611
- bool ImGui::InputFloat (const char* label, float *v, float step, float step_fast , int decimal_precision, ImGuiInputTextFlags extra_flags)
7667
+ static bool InputScalarEx (const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr , int decimal_precision, ImGuiInputTextFlags extra_flags)
7612
7668
{
7613
7669
ImGuiState& g = *GImGui;
7614
7670
ImGuiWindow* window = GetCurrentWindow();
@@ -7617,42 +7673,40 @@ bool ImGui::InputFloat(const char* label, float *v, float step, float step_fast,
7617
7673
7618
7674
const ImGuiStyle& style = g.Style;
7619
7675
const float w = ImGui::CalcItemWidth();
7620
- const ImVec2 label_size = CalcTextSize(label, NULL, true);
7676
+ const ImVec2 label_size = ImGui:: CalcTextSize(label, NULL, true);
7621
7677
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f);
7622
7678
7623
7679
ImGui::BeginGroup();
7624
7680
ImGui::PushID(label);
7625
7681
const ImVec2 button_sz = ImVec2(g.FontSize, g.FontSize) + style.FramePadding * 2;
7626
- if (step > 0.0f )
7682
+ if (step_ptr )
7627
7683
ImGui::PushItemWidth(ImMax(1.0f, w - (button_sz.x + style.ItemInnerSpacing.x)*2));
7628
7684
7629
7685
char buf[64];
7630
- if (decimal_precision < 0)
7631
- ImFormatString(buf, IM_ARRAYSIZE(buf), "%f", *v); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits?
7632
- else
7633
- ImFormatString(buf, IM_ARRAYSIZE(buf), "%.*f", decimal_precision, *v);
7686
+ DataTypeFormat(data_type, data_ptr, decimal_precision, buf, IM_ARRAYSIZE(buf));
7687
+
7634
7688
bool value_changed = false;
7635
7689
const ImGuiInputTextFlags flags = extra_flags | (ImGuiInputTextFlags_CharsDecimal|ImGuiInputTextFlags_AutoSelectAll);
7636
7690
if (ImGui::InputText("", buf, IM_ARRAYSIZE(buf), flags))
7637
7691
{
7638
- InputTextApplyArithmeticOp (buf, v );
7692
+ DataTypeApplyOpFromText (buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr );
7639
7693
value_changed = true;
7640
7694
}
7641
7695
7642
7696
// Step buttons
7643
- if (step > 0.0f )
7697
+ if (step_ptr )
7644
7698
{
7645
7699
ImGui::PopItemWidth();
7646
7700
ImGui::SameLine(0, style.ItemInnerSpacing.x);
7647
7701
if (ButtonEx("-", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))
7648
7702
{
7649
- *v -= g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step ;
7703
+ DataTypeApplyOp(data_type, ImGuiDataTypeOp_Sub, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr) ;
7650
7704
value_changed = true;
7651
7705
}
7652
7706
ImGui::SameLine(0, style.ItemInnerSpacing.x);
7653
7707
if (ButtonEx("+", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups))
7654
7708
{
7655
- *v += g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step ;
7709
+ DataTypeApplyOp(data_type, ImGuiDataTypeOp_Add, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr) ;
7656
7710
value_changed = true;
7657
7711
}
7658
7712
}
@@ -7669,13 +7723,14 @@ bool ImGui::InputFloat(const char* label, float *v, float step, float step_fast,
7669
7723
return value_changed;
7670
7724
}
7671
7725
7672
- bool ImGui::InputInt (const char* label, int * v, int step, int step_fast, ImGuiInputTextFlags extra_flags)
7726
+ bool ImGui::InputFloat (const char* label, float* v, float step, float step_fast, int decimal_precision , ImGuiInputTextFlags extra_flags)
7673
7727
{
7674
- float f = (float)*v;
7675
- const bool value_changed = ImGui::InputFloat(label, &f, (float)step, (float)step_fast, 0, extra_flags);
7676
- if (value_changed)
7677
- *v = (int)f;
7678
- return value_changed;
7728
+ return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), decimal_precision, extra_flags);
7729
+ }
7730
+
7731
+ bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags)
7732
+ {
7733
+ return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), 0, extra_flags);
7679
7734
}
7680
7735
7681
7736
static bool InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags)
0 commit comments