31 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
32 #define _CRT_SECURE_NO_WARNINGS
38 #ifndef IMGUI_DEFINE_MATH_OPERATORS
39 #define IMGUI_DEFINE_MATH_OPERATORS
44 #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
52 #pragma warning (disable: 4127) // condition expression is constant
53 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
54 #if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
55 #pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
60 #if defined(__clang__)
61 #pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
62 #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
63 #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
64 #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
65 #if __has_warning("-Wzero-as-null-pointer-constant")
66 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning : zero as null pointer constant // some standard header variations use #define NULL 0
68 #if __has_warning("-Wdouble-promotion")
69 #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
71 #if __has_warning("-Wdeprecated-enum-enum-conversion")
72 #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
74 #elif defined(__GNUC__)
75 #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
76 #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
77 #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
147 const char* text_begin = text;
148 if (text_end ==
NULL)
149 text_end = text + strlen(text);
153 const bool wrap_enabled = (wrap_pos_x >= 0.0f);
154 if (text_end - text > 2000 && !wrap_enabled)
161 const char* line = text;
169 int lines_skippable = (int)((window->
ClipRect.
Min.
y - text_pos.
y) / line_height);
170 if (lines_skippable > 0)
172 int lines_skipped = 0;
173 while (line < text_end && lines_skipped < lines_skippable)
175 const char* line_end = (
const char*)memchr(line,
'\n', text_end - line);
183 pos.
y += lines_skipped * line_height;
190 ImRect line_rect(pos, pos +
ImVec2(FLT_MAX, line_height));
191 while (line < text_end)
196 const char* line_end = (
const char*)memchr(line,
'\n', text_end - line);
202 line_rect.
Min.
y += line_height;
203 line_rect.
Max.
y += line_height;
204 pos.
y += line_height;
208 int lines_skipped = 0;
209 while (line < text_end)
211 const char* line_end = (
const char*)memchr(line,
'\n', text_end - line);
219 pos.
y += lines_skipped * line_height;
221 text_size.
y = (pos - text_pos).
y;
223 ImRect bb(text_pos, text_pos + text_size);
232 ImRect bb(text_pos, text_pos + text_size);
342 const char* value_text_begin = &
g.TempBuffer[0];
345 if (label_size.
x > 0.0f)
367 const char* text_begin =
g.TempBuffer;
374 const ImRect bb(pos, pos + total_size);
466 if (out_hovered) *out_hovered =
false;
467 if (out_held) *out_held =
false;
482 if (flatten_hovered_children)
483 g.HoveredWindow = window;
485 #ifdef IMGUI_ENABLE_TEST_ENGINE
487 ImGuiTestEngineHook_ItemAdd(&
g, bb,
id);
490 bool pressed =
false;
510 if (flatten_hovered_children)
511 g.HoveredWindow = backup_hovered_window;
523 int mouse_button_clicked = -1;
524 int mouse_button_released = -1;
532 if (mouse_button_clicked != -1 &&
g.ActiveId !=
id)
537 g.ActiveIdMouseButton = mouse_button_clicked;
549 g.ActiveIdMouseButton = mouse_button_clicked;
564 if (
g.IO.MouseDownDuration[
g.ActiveIdMouseButton] > 0.0f &&
IsMouseClicked(
g.ActiveIdMouseButton,
true))
569 g.NavDisableHighlight =
true;
574 if (
g.NavId ==
id && !
g.NavDisableHighlight &&
g.NavDisableMouseHover && (
g.ActiveId == 0 ||
g.ActiveId ==
id ||
g.ActiveId == window->
MoveId))
577 if (
g.NavActivateDownId ==
id)
579 bool nav_activated_by_code = (
g.NavActivateId ==
id);
581 if (nav_activated_by_code || nav_activated_by_inputs)
583 if (nav_activated_by_code || nav_activated_by_inputs ||
g.ActiveId ==
id)
586 g.NavActivateId =
id;
594 if (
g.ActiveId ==
id)
598 if (
g.ActiveIdIsJustActivated)
599 g.ActiveIdClickOffset =
g.IO.MousePos - bb.
Min;
601 const int mouse_button =
g.ActiveIdMouseButton;
603 if (
g.IO.MouseDown[mouse_button])
611 if ((release_in || release_anywhere) && !
g.DragDropActive)
615 if (!is_double_click_release && !is_repeating_already)
621 g.NavDisableHighlight =
true;
625 if (
g.NavActivateDownId !=
id)
629 g.ActiveIdHasBeenPressedBefore =
true;
632 if (out_hovered) *out_hovered = hovered;
633 if (out_held) *out_held = held;
688 g.Style.FramePadding.y = 0.0f;
690 g.Style.FramePadding.y = backup_padding_y;
703 IM_ASSERT(size_arg.
x != 0.0f && size_arg.
y != 0.0f);
762 const ImRect bb(pos, pos +
ImVec2(
g.FontSize,
g.FontSize) +
g.Style.FramePadding * 2.0f);
763 bool is_clipped = !
ItemAdd(bb,
id);
776 float cross_extent =
g.FontSize * 0.5f * 0.7071f - 1.0f;
790 ImRect bb(pos, pos +
ImVec2(
g.FontSize,
g.FontSize) +
g.Style.FramePadding * 2.0f);
828 const float bb_frame_width = bb_frame.
GetWidth();
829 const float bb_frame_height = bb_frame.
GetHeight();
830 if (bb_frame_width <= 0.0
f || bb_frame_height <= 0.0
f)
835 if ((axis ==
ImGuiAxis_Y) && bb_frame_height <
g.FontSize +
g.Style.FramePadding.y * 2.0f)
836 alpha =
ImSaturate((bb_frame_height -
g.FontSize) / (
g.Style.FramePadding.y * 2.0f));
841 const bool allow_interaction = (
alpha >= 1.0f);
853 const float win_size_v =
ImMax(
ImMax(size_contents_v, size_avail_v), 1.0
f);
854 const float grab_h_pixels =
ImClamp(scrollbar_size_v * (size_avail_v / win_size_v), style.
GrabMinSize, scrollbar_size_v);
855 const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
859 bool hovered =
false;
862 float scroll_max =
ImMax(1.0
f, size_contents_v - size_avail_v);
863 float scroll_ratio =
ImSaturate(*p_scroll_v / scroll_max);
864 float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
865 if (held && allow_interaction && grab_h_norm < 1.0
f)
867 float scrollbar_pos_v = horizontal ? bb.
Min.
x : bb.
Min.
y;
868 float mouse_pos_v = horizontal ?
g.IO.MousePos.x :
g.IO.MousePos.y;
871 const float clicked_v_norm =
ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
874 bool seek_absolute =
false;
875 if (
g.ActiveIdIsJustActivated)
878 seek_absolute = (clicked_v_norm < grab_v_norm || clicked_v_norm > grab_v_norm + grab_h_norm);
880 g.ScrollbarClickDeltaToGrabCenter = 0.0f;
882 g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
887 const float scroll_v_norm =
ImSaturate((clicked_v_norm -
g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
888 *p_scroll_v =
IM_ROUND(scroll_v_norm * scroll_max);
891 scroll_ratio =
ImSaturate(*p_scroll_v / scroll_max);
892 grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
896 g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
951 if (border_col.
w > 0.0f)
957 if (border_col.
w > 0.0f)
983 PushID((
void*)(intptr_t)user_texture_id);
987 const ImVec2 padding = (frame_padding >= 0) ?
ImVec2((
float)frame_padding, (float)frame_padding) : style.
FramePadding;
1001 if (bg_col.
w > 0.0f)
1034 const ImRect check_bb(pos, pos +
ImVec2(square_sz, square_sz));
1052 if (label_size.
x > 0.0f)
1061 bool v = ((*
flags & flags_value) == flags_value);
1066 *
flags |= flags_value;
1068 *
flags &= ~flags_value;
1087 const ImRect check_bb(pos, pos +
ImVec2(square_sz, square_sz));
1096 const float radius = (square_sz - 1.0f) * 0.5
f;
1119 if (label_size.
x > 0.0f)
1159 char overlay_buf[32];
1163 overlay = overlay_buf;
1167 if (overlay_size.
x > 0.0f)
1168 RenderTextClipped(
ImVec2(
ImClamp(fill_br.
x + style.
ItemSpacing.
x, bb.
Min.
x, bb.
Max.
x - overlay_size.
x - style.
ItemInnerSpacing.
x), bb.
Min.
y), bb.
Max, overlay,
NULL, &overlay_size,
ImVec2(0.0
f,0.5
f), &bb);
1263 float thickness_draw = 1.0f;
1264 float thickness_layout = 0.0f;
1283 float x1 = window->
Pos.
x;
1284 float x2 = window->
Pos.
x + window->
Size.
x;
1295 const bool item_visible =
ItemAdd(bb, 0);
1332 bool item_add =
ItemAdd(bb,
id);
1341 if (
g.ActiveId !=
id)
1344 if (held || (
g.HoveredId ==
id &&
g.HoveredIdPreviousFrame ==
id &&
g.HoveredIdTimer >= hover_visibility_delay))
1350 ImVec2 mouse_delta_2d =
g.IO.MousePos -
g.ActiveIdClickOffset - bb_interact.
Min;
1351 float mouse_delta = (axis ==
ImGuiAxis_Y) ? mouse_delta_2d.
y : mouse_delta_2d.
x;
1354 float size_1_maximum_delta =
ImMax(0.0
f, *size1 - min_size1);
1355 float size_2_maximum_delta =
ImMax(0.0
f, *size2 - min_size2);
1356 if (mouse_delta < -size_1_maximum_delta)
1357 mouse_delta = -size_1_maximum_delta;
1358 if (mouse_delta > size_2_maximum_delta)
1359 mouse_delta = size_2_maximum_delta;
1362 if (mouse_delta != 0.0
f)
1364 if (mouse_delta < 0.0
f)
1365 IM_ASSERT(*size1 + mouse_delta >= min_size1);
1366 if (mouse_delta > 0.0
f)
1367 IM_ASSERT(*size2 - mouse_delta >= min_size2);
1368 *size1 += mouse_delta;
1369 *size2 -= mouse_delta;
1386 if (
int d = (
int)(
b->Width -
a->Width))
1388 return (
b->Index -
a->Index);
1396 items[0].
Width =
ImMax(items[0].Width - width_excess, 1.0
f);
1400 int count_same_width = 1;
1401 while (width_excess > 0.0
f && count_same_width <
count)
1403 while (count_same_width <
count && items[0].Width <= items[count_same_width].Width)
1405 float max_width_to_remove_per_item = (count_same_width <
count) ? (items[0].Width - items[count_same_width].Width) : (items[0].
Width - 1.0f);
1406 float width_to_remove_per_item =
ImMin(width_excess / count_same_width, max_width_to_remove_per_item);
1407 for (
int item_n = 0; item_n < count_same_width; item_n++)
1408 items[item_n].Width -= width_to_remove_per_item;
1409 width_excess -= width_to_remove_per_item * count_same_width;
1414 width_excess = 0.0f;
1417 float width_rounded =
ImFloor(items[
n].Width);
1418 width_excess += items[
n].
Width - width_rounded;
1419 items[
n].
Width = width_rounded;
1421 if (width_excess > 0.0
f)
1423 if (items[
n].
Index < (
int)(width_excess + 0.01
f))
1438 if (items_count <= 0)
1440 return (
g.FontSize +
g.Style.ItemSpacing.y) * items_count -
g.
Style.
ItemSpacing.
y + (
g.Style.WindowPadding.y * 2);
1466 if (!
ItemAdd(total_bb,
id, &frame_bb))
1474 const float value_x2 =
ImMax(frame_bb.
Min.
x, frame_bb.
Max.
x - arrow_size);
1489 if (label_size.
x > 0)
1492 if ((pressed ||
g.NavActivateId ==
id) && !popup_open)
1503 if (has_window_size_constraint)
1506 g.NextWindowData.SizeConstraintRect.Min.x =
ImMax(
g.NextWindowData.SizeConstraintRect.Min.x,
w);
1513 int popup_max_height_in_items = -1;
1525 if (popup_window->WasActive)
1559 const char*
const* items = (
const char*
const*)
data;
1561 *out_text = items[
idx];
1569 const char* items_separated_by_zeros = (
const char*)
data;
1570 int items_count = 0;
1571 const char*
p = items_separated_by_zeros;
1574 if (
idx == items_count)
1587 bool ImGui::Combo(
const char*
label,
int* current_item,
bool (*items_getter)(
void*,
int,
const char**),
void*
data,
int items_count,
int popup_max_height_in_items)
1592 const char* preview_value =
NULL;
1593 if (*current_item >= 0 && *current_item < items_count)
1594 items_getter(
data, *current_item, &preview_value);
1605 bool value_changed =
false;
1606 for (
int i = 0;
i < items_count;
i++)
1609 const bool item_selected = (
i == *current_item);
1610 const char* item_text;
1611 if (!items_getter(
data,
i, &item_text))
1612 item_text =
"*Unknown item*";
1615 value_changed =
true;
1624 return value_changed;
1628 bool ImGui::Combo(
const char*
label,
int* current_item,
const char*
const items[],
int items_count,
int height_in_items)
1631 return value_changed;
1635 bool ImGui::Combo(
const char*
label,
int* current_item,
const char* items_separated_by_zeros,
int height_in_items)
1637 int items_count = 0;
1638 const char*
p = items_separated_by_zeros;
1645 return value_changed;
1662 {
sizeof(char),
"%d",
"%d" },
1663 {
sizeof(
unsigned char),
"%u",
"%u" },
1664 {
sizeof(short),
"%d",
"%d" },
1665 {
sizeof(
unsigned short),
"%u",
"%u" },
1666 {
sizeof(int),
"%d",
"%d" },
1667 {
sizeof(
unsigned int),
"%u",
"%u" },
1669 {
sizeof(
ImS64),
"%I64d",
"%I64d" },
1670 {
sizeof(
ImU64),
"%I64u",
"%I64u" },
1672 {
sizeof(
ImS64),
"%lld",
"%lld" },
1673 {
sizeof(
ImU64),
"%llu",
"%llu" },
1675 {
sizeof(float),
"%f",
"%f" },
1676 {
sizeof(double),
"%f",
"%lf" },
1685 if (
fmt[0] ==
'%' &&
fmt[1] ==
'.' &&
fmt[2] ==
'0' &&
fmt[3] ==
'f' &&
fmt[4] == 0)
1689 if (fmt_end > fmt_start && fmt_end[-1] ==
'f')
1691 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1692 if (fmt_start ==
fmt && fmt_end[0] == 0)
1696 return g.TempBuffer;
1698 IM_ASSERT(0 &&
"DragInt(): Invalid format string!");
1771 if (op ==
'+') { *(
float*)
output = *(
const float*)arg1 + *(
const float*)arg2; }
1772 if (op ==
'-') { *(
float*)
output = *(
const float*)arg1 - *(
const float*)arg2; }
1775 if (op ==
'+') { *(
double*)
output = *(
const double*)arg1 + *(
const double*)arg2; }
1776 if (op ==
'-') { *(
double*)
output = *(
const double*)arg1 - *(
const double*)arg2; }
1793 if (op ==
'+' || op ==
'*' || op ==
'/')
1811 memcpy(data_backup, p_data, type_info->
Size);
1820 int*
v = (
int*)p_data;
1823 if (op && sscanf(initial_value_buf,
format, &arg0i) < 1)
1826 if (op ==
'+') {
if (sscanf(
buf,
"%d", &arg1i)) *
v = (
int)(arg0i + arg1i); }
1827 else if (op ==
'*') {
if (sscanf(
buf,
"%f", &arg1f)) *
v = (
int)(arg0i * arg1f); }
1828 else if (op ==
'/') {
if (sscanf(
buf,
"%f", &arg1f) && arg1f != 0.0f) *
v = (
int)(arg0i / arg1f); }
1829 else {
if (sscanf(
buf,
format, &arg1i) == 1) *
v = arg1i; }
1835 float*
v = (
float*)p_data;
1836 float arg0f = *
v, arg1f = 0.0f;
1837 if (op && sscanf(initial_value_buf,
format, &arg0f) < 1)
1841 if (op ==
'+') { *
v = arg0f + arg1f; }
1842 else if (op ==
'*') { *
v = arg0f * arg1f; }
1843 else if (op ==
'/') {
if (arg1f != 0.0
f) *
v = arg0f / arg1f; }
1844 else { *
v = arg1f; }
1849 double*
v = (
double*)p_data;
1850 double arg0f = *
v, arg1f = 0.0;
1851 if (op && sscanf(initial_value_buf,
format, &arg0f) < 1)
1855 if (op ==
'+') { *
v = arg0f + arg1f; }
1856 else if (op ==
'*') { *
v = arg0f * arg1f; }
1857 else if (op ==
'/') {
if (arg1f != 0.0
f) *
v = arg0f / arg1f; }
1858 else { *
v = arg1f; }
1883 return memcmp(data_backup, p_data, type_info->
Size) != 0;
1888 static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f };
1889 if (decimal_precision < 0)
1891 return (decimal_precision <
IM_ARRAYSIZE(min_steps)) ? min_steps[decimal_precision] :
ImPow(10.0
f, (
float)-decimal_precision);
1894 template<
typename TYPE>
1898 if (*
src ==
'-') { negative = 1;
src++; }
1899 if (*
src ==
'+') {
src++; }
1901 while (*
src >=
'0' && *
src <=
'9')
1902 v = (
v * 10) + (*
src++ -
'0');
1907 template<
typename TYPE,
typename SIGNEDTYPE>
1911 if (fmt_start[0] !=
'%' || fmt_start[1] ==
'%')
1915 const char*
p = v_str;
1945 template<
typename TYPE,
typename SIGNEDTYPE,
typename FLOATTYPE>
1951 const bool is_clamped = (v_min < v_max);
1952 const bool is_power = (power != 1.0f && is_decimal && is_clamped && (v_max - v_min < FLT_MAX));
1953 const bool is_locked = (v_min > v_max);
1958 if (v_speed == 0.0
f && is_clamped && (v_max - v_min < FLT_MAX))
1959 v_speed = (
float)((v_max - v_min) *
g.DragSpeedDefaultRatio);
1962 float adjust_delta = 0.0f;
1965 adjust_delta =
g.IO.MouseDelta[axis];
1967 adjust_delta *= 1.0f / 100.0f;
1969 adjust_delta *= 10.0f;
1977 adjust_delta *= v_speed;
1981 adjust_delta = -adjust_delta;
1985 bool is_just_activated =
g.ActiveIdIsJustActivated;
1986 bool is_already_past_limits_and_pushing_outward = is_clamped && ((*
v >= v_max && adjust_delta > 0.0f) || (*
v <= v_min && adjust_delta < 0.0
f));
1987 bool is_drag_direction_change_with_power = is_power && ((adjust_delta < 0 &&
g.DragCurrentAccum > 0) || (adjust_delta > 0 &&
g.DragCurrentAccum < 0));
1988 if (is_just_activated || is_already_past_limits_and_pushing_outward || is_drag_direction_change_with_power)
1990 g.DragCurrentAccum = 0.0f;
1991 g.DragCurrentAccumDirty =
false;
1993 else if (adjust_delta != 0.0
f)
1995 g.DragCurrentAccum += adjust_delta;
1996 g.DragCurrentAccumDirty =
true;
1999 if (!
g.DragCurrentAccumDirty)
2003 FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0
f;
2008 FLOATTYPE v_old_norm_curved =
ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0
f / power);
2009 FLOATTYPE v_new_norm_curved = v_old_norm_curved + (
g.DragCurrentAccum / (v_max - v_min));
2010 v_cur = v_min + (SIGNEDTYPE)
ImPow(
ImSaturate((
float)v_new_norm_curved), power) * (v_max - v_min);
2011 v_old_ref_for_accum_remainder = v_old_norm_curved;
2015 v_cur += (SIGNEDTYPE)
g.DragCurrentAccum;
2019 v_cur = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(
format, data_type, v_cur);
2022 g.DragCurrentAccumDirty =
false;
2025 FLOATTYPE v_cur_norm_curved =
ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0
f / power);
2026 g.DragCurrentAccum -= (float)(v_cur_norm_curved - v_old_ref_for_accum_remainder);
2030 g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*
v);
2034 if (v_cur == (
TYPE)-0)
2038 if (*
v != v_cur && is_clamped)
2040 if (v_cur < v_min || (v_cur > *
v && adjust_delta < 0.0
f && !is_decimal))
2042 if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0
f && !is_decimal))
2056 if (
g.ActiveId ==
id)
2060 else if (
g.ActiveIdSource ==
ImGuiInputSource_Nav &&
g.NavActivatePressedId ==
id && !
g.ActiveIdIsJustActivated)
2063 if (
g.ActiveId !=
id)
2076 case ImGuiDataType_Float:
return DragBehaviorT<float, float, float >(data_type, (
float*)p_v, v_speed, p_min ? *(
const float* )p_min : -FLT_MAX, p_max ? *(
const float* )p_max : FLT_MAX,
format, power,
flags);
2077 case ImGuiDataType_Double:
return DragBehaviorT<double,double,double>(data_type, (
double*)p_v, v_speed, p_min ? *(
const double*)p_min : -DBL_MAX, p_max ? *(
const double*)p_max : DBL_MAX,
format, power,
flags);
2104 if (!
ItemAdd(total_bb,
id, &frame_bb))
2116 bool temp_input_start =
false;
2117 if (!temp_input_is_active)
2120 const bool clicked = (hovered &&
g.IO.MouseClicked[0]);
2121 const bool double_clicked = (hovered &&
g.IO.MouseDoubleClicked[0]);
2122 if (focus_requested || clicked || double_clicked ||
g.NavActivateId ==
id ||
g.NavInputId ==
id)
2128 if (focus_requested || (clicked &&
g.IO.KeyCtrl) || double_clicked ||
g.NavInputId ==
id)
2130 temp_input_start =
true;
2135 if (temp_input_is_active || temp_input_start)
2153 if (label_size.
x > 0.0f)
2157 return value_changed;
2167 bool value_changed =
false;
2172 for (
int i = 0;
i < components;
i++)
2176 SameLine(0,
g.Style.ItemInnerSpacing.x);
2177 value_changed |=
DragScalar(
"", data_type, p_data, v_speed, p_min, p_max,
format, power);
2180 p_data = (
void*)((
char*)p_data + type_size);
2185 if (
label != label_end)
2187 SameLine(0,
g.Style.ItemInnerSpacing.x);
2192 return value_changed;
2215 bool ImGui::DragFloatRange2(
const char*
label,
float* v_current_min,
float* v_current_max,
float v_speed,
float v_min,
float v_max,
const char*
format,
const char* format_max,
float power)
2226 bool value_changed =
DragFloat(
"##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max :
ImMin(v_max, *v_current_max),
format, power);
2228 SameLine(0,
g.Style.ItemInnerSpacing.x);
2229 value_changed |=
DragFloat(
"##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min :
ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, format_max ? format_max :
format, power);
2231 SameLine(0,
g.Style.ItemInnerSpacing.x);
2236 return value_changed;
2271 bool value_changed =
DragInt(
"##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max :
ImMin(v_max, *v_current_max),
format);
2273 SameLine(0,
g.Style.ItemInnerSpacing.x);
2274 value_changed |=
DragInt(
"##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min :
ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, format_max ? format_max :
format);
2276 SameLine(0,
g.Style.ItemInnerSpacing.x);
2282 return value_changed;
2306 template<
typename TYPE,
typename FLOATTYPE>
2316 if (v_clamped < 0.0
f)
2318 const float f = 1.0f - (float)((v_clamped - v_min) / (
ImMin((
TYPE)0, v_max) - v_min));
2319 return (1.0
f -
ImPow(
f, 1.0
f/power)) * linear_zero_pos;
2323 const float f = (float)((v_clamped -
ImMax((
TYPE)0, v_min)) / (v_max -
ImMax((
TYPE)0, v_min)));
2324 return linear_zero_pos +
ImPow(
f, 1.0
f/power) * (1.0f - linear_zero_pos);
2329 return (
float)((FLOATTYPE)(v_clamped - v_min) / (FLOATTYPE)(v_max - v_min));
2333 template<
typename TYPE,
typename SIGNEDTYPE,
typename FLOATTYPE>
2341 const bool is_power = (power != 1.0f) && is_decimal;
2343 const float grab_padding = 2.0f;
2344 const float slider_sz = (bb.
Max[axis] - bb.
Min[axis]) - grab_padding * 2.0
f;
2346 SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
2347 if (!is_decimal && v_range >= 0)
2349 grab_sz =
ImMin(grab_sz, slider_sz);
2350 const float slider_usable_sz = slider_sz - grab_sz;
2351 const float slider_usable_pos_min = bb.
Min[axis] + grab_padding + grab_sz * 0.5f;
2352 const float slider_usable_pos_max = bb.
Max[axis] - grab_padding - grab_sz * 0.5f;
2355 float linear_zero_pos;
2356 if (is_power && v_min * v_max < 0.0
f)
2359 const FLOATTYPE linear_dist_min_to_0 =
ImPow(v_min >= 0 ? (FLOATTYPE)v_min : -(FLOATTYPE)v_min, (FLOATTYPE)1.0
f / power);
2360 const FLOATTYPE linear_dist_max_to_0 =
ImPow(v_max >= 0 ? (FLOATTYPE)v_max : -(FLOATTYPE)v_max, (FLOATTYPE)1.0
f / power);
2361 linear_zero_pos = (float)(linear_dist_min_to_0 / (linear_dist_min_to_0 + linear_dist_max_to_0));
2366 linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f;
2370 bool value_changed =
false;
2371 if (
g.ActiveId ==
id)
2373 bool set_new_value =
false;
2374 float clicked_t = 0.0f;
2377 if (!
g.IO.MouseDown[0])
2383 const float mouse_abs_pos =
g.IO.MousePos[axis];
2384 clicked_t = (slider_usable_sz > 0.0f) ?
ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0
f;
2386 clicked_t = 1.0f - clicked_t;
2387 set_new_value =
true;
2394 if (
g.NavActivatePressedId ==
id && !
g.ActiveIdIsJustActivated)
2398 else if (delta != 0.0
f)
2400 clicked_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *
v, v_min, v_max, power, linear_zero_pos);
2402 if ((decimal_precision > 0) || is_power)
2411 delta = ((delta < 0.0f) ? -1.0
f : +1.0
f) / (float)v_range;
2417 set_new_value =
true;
2418 if ((clicked_t >= 1.0
f && delta > 0.0
f) || (clicked_t <= 0.0f && delta < 0.0f))
2419 set_new_value =
false;
2431 if (clicked_t < linear_zero_pos)
2434 float a = 1.0f - (clicked_t / linear_zero_pos);
2442 if (
ImFabs(linear_zero_pos - 1.0
f) > 1.e-6
f)
2443 a = (clicked_t - linear_zero_pos) / (1.0
f - linear_zero_pos);
2455 v_new =
ImLerp(v_min, v_max, clicked_t);
2461 FLOATTYPE v_new_off_f = (v_max - v_min) * clicked_t;
2462 TYPE v_new_off_floor = (
TYPE)(v_new_off_f);
2463 TYPE v_new_off_round = (
TYPE)(v_new_off_f + (FLOATTYPE)0.5);
2464 if (v_new_off_floor < v_new_off_round)
2465 v_new = v_min + v_new_off_round;
2467 v_new = v_min + v_new_off_floor;
2472 v_new = RoundScalarWithFormatT<TYPE,SIGNEDTYPE>(
format, data_type, v_new);
2478 value_changed =
true;
2483 if (slider_sz < 1.0
f)
2490 float grab_t = SliderCalcRatioFromValueT<TYPE, FLOATTYPE>(data_type, *
v, v_min, v_max, power, linear_zero_pos);
2492 grab_t = 1.0f - grab_t;
2493 const float grab_pos =
ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
2495 *out_grab_bb =
ImRect(grab_pos - grab_sz * 0.5
f, bb.
Min.
y + grab_padding, grab_pos + grab_sz * 0.5f, bb.
Max.
y - grab_padding);
2497 *out_grab_bb =
ImRect(bb.
Min.
x + grab_padding, grab_pos - grab_sz * 0.5f, bb.
Max.
x - grab_padding, grab_pos + grab_sz * 0.5f);
2500 return value_changed;
2510 case ImGuiDataType_S8: {
ImS32 v32 = (
ImS32)*(
ImS8*)p_v;
bool r = SliderBehaviorT<ImS32, ImS32, float>(bb,
id,
ImGuiDataType_S32, &v32, *(
const ImS8*)p_min, *(
const ImS8*)p_max,
format, power,
flags, out_grab_bb);
if (
r) *(
ImS8*)p_v = (
ImS8)v32;
return r; }
2511 case ImGuiDataType_U8: {
ImU32 v32 = (
ImU32)*(
ImU8*)p_v;
bool r = SliderBehaviorT<ImU32, ImS32, float>(bb,
id,
ImGuiDataType_U32, &v32, *(
const ImU8*)p_min, *(
const ImU8*)p_max,
format, power,
flags, out_grab_bb);
if (
r) *(
ImU8*)p_v = (
ImU8)v32;
return r; }
2512 case ImGuiDataType_S16: {
ImS32 v32 = (
ImS32)*(
ImS16*)p_v;
bool r = SliderBehaviorT<ImS32, ImS32, float>(bb,
id,
ImGuiDataType_S32, &v32, *(
const ImS16*)p_min, *(
const ImS16*)p_max,
format, power,
flags, out_grab_bb);
if (
r) *(
ImS16*)p_v = (
ImS16)v32;
return r; }
2513 case ImGuiDataType_U16: {
ImU32 v32 = (
ImU32)*(
ImU16*)p_v;
bool r = SliderBehaviorT<ImU32, ImS32, float>(bb,
id,
ImGuiDataType_U32, &v32, *(
const ImU16*)p_min, *(
const ImU16*)p_max,
format, power,
flags, out_grab_bb);
if (
r) *(
ImU16*)p_v = (
ImU16)v32;
return r; }
2516 return SliderBehaviorT<ImS32, ImS32, float >(bb,
id, data_type, (
ImS32*)p_v, *(
const ImS32*)p_min, *(
const ImS32*)p_max,
format, power,
flags, out_grab_bb);
2519 return SliderBehaviorT<ImU32, ImS32, float >(bb,
id, data_type, (
ImU32*)p_v, *(
const ImU32*)p_min, *(
const ImU32*)p_max,
format, power,
flags, out_grab_bb);
2522 return SliderBehaviorT<ImS64, ImS64, double>(bb,
id, data_type, (
ImS64*)p_v, *(
const ImS64*)p_min, *(
const ImS64*)p_max,
format, power,
flags, out_grab_bb);
2525 return SliderBehaviorT<ImU64, ImS64, double>(bb,
id, data_type, (
ImU64*)p_v, *(
const ImU64*)p_min, *(
const ImU64*)p_max,
format, power,
flags, out_grab_bb);
2527 IM_ASSERT(*(
const float*)p_min >= -FLT_MAX/2.0
f && *(
const float*)p_max <= FLT_MAX/2.0
f);
2528 return SliderBehaviorT<float, float, float >(bb,
id, data_type, (
float*)p_v, *(
const float*)p_min, *(
const float*)p_max,
format, power,
flags, out_grab_bb);
2530 IM_ASSERT(*(
const double*)p_min >= -DBL_MAX/2.0
f && *(
const double*)p_max <= DBL_MAX/2.0
f);
2531 return SliderBehaviorT<double,double,double>(bb,
id, data_type, (
double*)p_v, *(
const double*)p_min, *(
const double*)p_max,
format, power,
flags, out_grab_bb);
2556 if (!
ItemAdd(total_bb,
id, &frame_bb))
2568 bool temp_input_start =
false;
2569 if (!temp_input_is_active)
2572 const bool clicked = (hovered &&
g.IO.MouseClicked[0]);
2573 if (focus_requested || clicked ||
g.NavActivateId ==
id ||
g.NavInputId ==
id)
2579 if (focus_requested || (clicked &&
g.IO.KeyCtrl) ||
g.NavInputId ==
id)
2581 temp_input_start =
true;
2586 if (temp_input_is_active || temp_input_start)
2609 if (label_size.
x > 0.0f)
2613 return value_changed;
2624 bool value_changed =
false;
2629 for (
int i = 0;
i < components;
i++)
2633 SameLine(0,
g.Style.ItemInnerSpacing.x);
2637 v = (
void*)((
char*)
v + type_size);
2642 if (
label != label_end)
2644 SameLine(0,
g.Style.ItemInnerSpacing.x);
2649 return value_changed;
2676 float v_deg = (*v_rad) * 360.0f / (2*
IM_PI);
2678 *v_rad = v_deg * (2*
IM_PI) / 360.0
f;
2679 return value_changed;
2727 if ((hovered &&
g.IO.MouseClicked[0]) ||
g.NavActivateId ==
id ||
g.NavInputId ==
id)
2755 if (label_size.
x > 0.0f)
2758 return value_changed;
2795 while (
char c =
fmt[0])
2797 if (c ==
'%' &&
fmt[1] !=
'%')
2811 const unsigned int ignored_uppercase_mask = (1 << (
'I'-
'A')) | (1 << (
'L'-
'A'));
2812 const unsigned int ignored_lowercase_mask = (1 << (
'h'-
'a')) | (1 << (
'j'-
'a')) | (1 << (
'l'-
'a')) | (1 << (
't'-
'a')) | (1 << (
'w'-
'a')) | (1 << (
'z'-
'a'));
2813 for (
char c; (c = *
fmt) != 0;
fmt++)
2815 if (c >=
'A' && c <=
'Z' && ((1 << (c -
'A')) & ignored_uppercase_mask) == 0)
2817 if (c >=
'a' && c <=
'z' && ((1 << (c -
'a')) & ignored_lowercase_mask) == 0)
2831 if (fmt_start[0] !=
'%')
2834 if (fmt_end[0] == 0)
2846 return default_precision;
2848 while (*
fmt >=
'0' && *
fmt <=
'9')
2857 if (*
fmt ==
'e' || *
fmt ==
'E')
2871 const bool init = (
g.TempInputId !=
id);
2875 g.CurrentWindow->DC.CursorPos = bb.
Min;
2881 g.TempInputId =
g.ActiveId;
2883 return value_changed;
2905 return value_changed;
2925 bool value_changed =
false;
2948 if (
ButtonEx(
"-",
ImVec2(button_size, button_size), button_flags))
2950 DataTypeApplyOp(data_type,
'-', p_data, p_data,
g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
2951 value_changed =
true;
2954 if (
ButtonEx(
"+",
ImVec2(button_size, button_size), button_flags))
2956 DataTypeApplyOp(data_type,
'+', p_data, p_data,
g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
2957 value_changed =
true;
2961 if (
label != label_end)
2979 return value_changed;
2989 bool value_changed =
false;
2994 for (
int i = 0;
i < components;
i++)
2998 SameLine(0,
g.Style.ItemInnerSpacing.x);
3002 p_data = (
void*)((
char*)p_data + type_size);
3007 if (
label != label_end)
3014 return value_changed;
3039 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
3043 if (decimal_precision >= 0)
3051 if (decimal_precision >= 0)
3059 if (decimal_precision >= 0)
3067 if (decimal_precision >= 0)
3071 #endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
3130 const char*
s = text_begin;
3131 while (
char c = *
s++)
3135 if (
s[0] !=
'\n' &&
s[0] !=
'\r')
3146 const float scale = line_height / font->
FontSize;
3149 float line_width = 0.0f;
3152 while (
s < text_end)
3154 unsigned int c = (
unsigned int)(*
s++);
3157 text_size.
x =
ImMax(text_size.
x, line_width);
3158 text_size.
y += line_height;
3160 if (stop_on_new_line)
3168 line_width += char_width;
3171 if (text_size.
x < line_width)
3172 text_size.
x = line_width;
3175 *out_offset =
ImVec2(line_width, text_size.
y + line_height);
3177 if (line_width > 0 || text_size.
y == 0.0f)
3178 text_size.
y += line_height;
3202 r->baseline_y_delta =
size.y;
3205 r->num_chars = (int)(text_remaining - (text + line_start_idx));
3208 static bool is_separator(
unsigned int c) {
return ImCharIsBlankW(c) || c==
',' || c==
';' || c==
'(' || c==
')' || c==
'{' || c==
'}' || c==
'[' || c==
']' || c==
'|'; }
3211 #ifdef __APPLE__ // FIXME: Move setting to IO structure
3217 #define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
3218 #define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
3238 const int text_len =
obj->CurLenW;
3242 if (!is_resizable && (new_text_len_utf8 +
obj->CurLenA + 1 >
obj->BufCapacityA))
3246 if (new_text_len + text_len + 1 >
obj->TextW.Size)
3251 obj->TextW.resize(text_len +
ImClamp(new_text_len * 4, 32,
ImMax(256, new_text_len)) + 1);
3255 if (pos != text_len)
3256 memmove(text + pos + new_text_len, text + pos, (
size_t)(text_len - pos) *
sizeof(
ImWchar));
3257 memcpy(text + pos, new_text, (
size_t)new_text_len *
sizeof(
ImWchar));
3259 obj->CurLenW += new_text_len;
3260 obj->CurLenA += new_text_len_utf8;
3261 obj->TextW[
obj->CurLenW] =
'\0';
3267 #define STB_TEXTEDIT_K_LEFT 0x200000 // keyboard input to move cursor left
3268 #define STB_TEXTEDIT_K_RIGHT 0x200001 // keyboard input to move cursor right
3269 #define STB_TEXTEDIT_K_UP 0x200002 // keyboard input to move cursor up
3270 #define STB_TEXTEDIT_K_DOWN 0x200003 // keyboard input to move cursor down
3271 #define STB_TEXTEDIT_K_LINESTART 0x200004 // keyboard input to move cursor to start of line
3272 #define STB_TEXTEDIT_K_LINEEND 0x200005 // keyboard input to move cursor to end of line
3273 #define STB_TEXTEDIT_K_TEXTSTART 0x200006 // keyboard input to move cursor to start of text
3274 #define STB_TEXTEDIT_K_TEXTEND 0x200007 // keyboard input to move cursor to end of text
3275 #define STB_TEXTEDIT_K_DELETE 0x200008 // keyboard input to delete selection or character under cursor
3276 #define STB_TEXTEDIT_K_BACKSPACE 0x200009 // keyboard input to delete selection or character left of cursor
3277 #define STB_TEXTEDIT_K_UNDO 0x20000A // keyboard input to perform undo
3278 #define STB_TEXTEDIT_K_REDO 0x20000B // keyboard input to perform redo
3279 #define STB_TEXTEDIT_K_WORDLEFT 0x20000C // keyboard input to move cursor left one word
3280 #define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word
3281 #define STB_TEXTEDIT_K_SHIFT 0x400000
3283 #define STB_TEXTEDIT_IMPLEMENTATION
3290 stb_text_makeundo_replace(
str, state, 0,
str->CurLenW, text_len);
3296 state->
cursor = text_len;
3307 stb_textedit_key(
this, &
Stb,
key);
3314 memset(
this, 0,
sizeof(*
this));
3324 const char*
src =
Buf + pos + bytes_count;
3325 while (
char c = *
src++)
3341 const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
3360 memcpy(
Buf + pos, new_text, (
size_t)new_text_len *
sizeof(
char));
3373 unsigned int c = *p_char;
3390 if (c >= 0xE000 && c <= 0xF8FF)
3401 if (!(c >=
'0' && c <=
'9') && (c !=
'.') && (c !=
'-') && (c !=
'+') && (c !=
'*') && (c !=
'/'))
3405 if (!(c >=
'0' && c <=
'9') && (c !=
'.') && (c !=
'-') && (c !=
'+') && (c !=
'*') && (c !=
'/') && (c !=
'e') && (c !=
'E'))
3409 if (!(c >=
'0' && c <=
'9') && !(c >=
'a' && c <=
'f') && !(c >=
'A' && c <=
'F'))
3413 if (c >=
'a' && c <=
'z')
3414 *p_char = (c += (
unsigned int)(
'A'-
'a'));
3429 callback_data.
UserData = user_data;
3430 if (callback(&callback_data) != 0)
3461 const bool RENDER_SELECTION_WHEN_INACTIVE =
false;
3478 const ImRect total_bb(frame_bb.
Min, frame_bb.
Min + total_size);
3481 ImVec2 inner_size = frame_size;
3484 if (!
ItemAdd(total_bb,
id, &frame_bb))
3505 draw_window =
g.CurrentWindow;
3512 if (!
ItemAdd(total_bb,
id, &frame_bb))
3523 const bool focus_requested_by_code = focus_requested && (
g.FocusRequestCurrWindow == window &&
g.FocusRequestCurrCounterRegular == window->
DC.
FocusCounterRegular);
3524 const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
3526 const bool user_clicked = hovered && io.
MouseClicked[0];
3531 bool clear_active_id =
false;
3534 const bool init_make_active = (focus_requested || user_clicked || user_scroll_finish || user_nav_input_start);
3535 const bool init_state = (init_make_active || user_scroll_active);
3536 if (init_state &&
g.ActiveId !=
id)
3539 state = &
g.InputTextState;
3544 const int buf_len = (int)strlen(
buf);
3549 const char* buf_end =
NULL;
3558 const bool recycle_state = (state->
ID ==
id);
3569 stb_textedit_initialize_state(&state->
Stb, !is_multiline);
3570 if (!is_multiline && focus_requested_by_code)
3574 state->
Stb.insert_mode = 1;
3575 if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.
KeyCtrl)))
3579 if (
g.ActiveId !=
id && init_make_active)
3600 if (
g.ActiveId ==
id && state ==
NULL)
3604 if (
g.ActiveId ==
id && io.
MouseClicked[0] && !init_state && !init_make_active)
3605 clear_active_id =
true;
3608 const bool render_cursor = (
g.ActiveId ==
id) || (state && user_scroll_active);
3609 bool render_selection = state && state->
HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
3610 bool value_changed =
false;
3611 bool enter_pressed =
false;
3615 if (is_readonly && state !=
NULL && (render_cursor || render_selection))
3617 const char* buf_end =
NULL;
3626 const bool buf_display_from_state = (render_cursor || render_selection ||
g.ActiveId ==
id) && !is_readonly && state && state->
TextAIsValid;
3627 const bool is_displaying_hint = (hint !=
NULL && (buf_display_from_state ? state->
TextA.
Data :
buf)[0] == 0);
3630 if (is_password && !is_displaying_hint)
3633 ImFont* password_font = &
g.InputTextPasswordFont;
3634 password_font->
FontSize =
g.Font->FontSize;
3635 password_font->
Scale =
g.Font->Scale;
3637 password_font->
Ascent =
g.Font->Ascent;
3638 password_font->
Descent =
g.Font->Descent;
3647 int backup_current_text_length = 0;
3648 if (
g.ActiveId ==
id)
3651 backup_current_text_length = state->
CurLenA;
3660 g.WantTextInputNextFrame = 1;
3682 stb_textedit_click(state, &state->
Stb, mouse_x, mouse_y);
3688 stb_textedit_drag(state, &state->
Stb, mouse_x, mouse_y);
3701 unsigned int c =
'\t';
3710 if (!ignore_char_inputs && !is_readonly && !user_nav_input_start)
3727 bool cancel_edit =
false;
3728 if (
g.ActiveId ==
id && !
g.ActiveIdIsJustActivated && !clear_active_id)
3735 const bool is_wordmove_key_down = is_osx ? io.
KeyAlt : io.
KeyCtrl;
3757 if (is_wordmove_key_down)
3767 if (!is_multiline || (ctrl_enter_for_new_line && !io.
KeyCtrl) || (!ctrl_enter_for_new_line && io.
KeyCtrl))
3769 enter_pressed = clear_active_id =
true;
3771 else if (!is_readonly)
3773 unsigned int c =
'\n';
3780 clear_active_id = cancel_edit =
true;
3782 else if (is_undo || is_redo)
3792 else if (is_cut || is_copy)
3800 char* clipboard_data = (
char*)
IM_ALLOC(clipboard_data_len *
sizeof(
char));
3810 stb_textedit_cut(state, &state->
Stb);
3818 const int clipboard_len = (int)strlen(clipboard);
3820 int clipboard_filtered_len = 0;
3821 for (
const char*
s = clipboard; *
s; )
3829 clipboard_filtered[clipboard_filtered_len++] = (
ImWchar)c;
3831 clipboard_filtered[clipboard_filtered_len] = 0;
3832 if (clipboard_filtered_len > 0)
3834 stb_textedit_paste(state, &state->
Stb, clipboard_filtered, clipboard_filtered_len);
3842 render_selection |= state->
HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
3846 if (
g.ActiveId ==
id)
3849 const char* apply_new_text =
NULL;
3850 int apply_new_text_length = 0;
3860 if (apply_new_text_length > 0)
3873 if (apply_edit_back_to_user_buffer)
3918 callback_data.
UserData = callback_user_data;
3920 callback_data.
EventKey = event_key;
3933 callback(&callback_data);
3945 if (callback_data.
BufTextLen > backup_current_text_length && is_resizable)
3955 if (!is_readonly && strcmp(state->
TextA.
Data,
buf) != 0)
3958 apply_new_text_length = state->
CurLenA;
3975 callback_data.
BufTextLen = apply_new_text_length;
3976 callback_data.
BufSize =
ImMax(buf_size, apply_new_text_length + 1);
3977 callback_data.
UserData = callback_user_data;
3978 callback(&callback_data);
3980 buf_size = callback_data.
BufSize;
3981 apply_new_text_length =
ImMin(callback_data.
BufTextLen, buf_size - 1);
3982 IM_ASSERT(apply_new_text_length <= buf_size);
3988 value_changed =
true;
3998 if (clear_active_id &&
g.ActiveId ==
id)
4008 const ImVec4 clip_rect(frame_bb.
Min.
x, frame_bb.
Min.
y, frame_bb.
Min.
x + inner_size.
x, frame_bb.
Min.
y + inner_size.
y);
4015 const int buf_display_max_length = 2 * 1024 * 1024;
4016 const char* buf_display = buf_display_from_state ? state->
TextA.
Data :
buf;
4017 const char* buf_display_end =
NULL;
4018 if (is_displaying_hint)
4021 buf_display_end = hint + strlen(hint);
4026 if (render_cursor || render_selection)
4029 if (!is_displaying_hint)
4030 buf_display_end = buf_display + state->
CurLenA;
4040 ImVec2 cursor_offset, select_start_offset;
4045 int searches_result_line_no[2] = { -1000, -1000 };
4046 int searches_remaining = 0;
4049 searches_input_ptr[0] = text_begin + state->
Stb.cursor;
4050 searches_result_line_no[0] = -1;
4051 searches_remaining++;
4053 if (render_selection)
4055 searches_input_ptr[1] = text_begin +
ImMin(state->
Stb.select_start, state->
Stb.select_end);
4056 searches_result_line_no[1] = -1;
4057 searches_remaining++;
4062 searches_remaining += is_multiline ? 1 : 0;
4065 for (
const ImWchar*
s = text_begin; *
s != 0;
s++)
4069 if (searches_result_line_no[0] == -1 &&
s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count;
if (--searches_remaining <= 0)
break; }
4070 if (searches_result_line_no[1] == -1 &&
s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count;
if (--searches_remaining <= 0)
break; }
4073 if (searches_result_line_no[0] == -1)
4074 searches_result_line_no[0] = line_count;
4075 if (searches_result_line_no[1] == -1)
4076 searches_result_line_no[1] = line_count;
4080 cursor_offset.
y = searches_result_line_no[0] *
g.FontSize;
4081 if (searches_result_line_no[1] >= 0)
4084 select_start_offset.
y = searches_result_line_no[1] *
g.FontSize;
4089 text_size =
ImVec2(inner_size.
x, line_count *
g.FontSize);
4098 const float scroll_increment_x = inner_size.
x * 0.25f;
4099 if (cursor_offset.
x < state->
ScrollX)
4101 else if (cursor_offset.
x - inner_size.
x >= state->
ScrollX)
4112 float scroll_y = draw_window->
Scroll.
y;
4113 if (cursor_offset.
y -
g.FontSize < scroll_y)
4114 scroll_y =
ImMax(0.0
f, cursor_offset.
y -
g.FontSize);
4115 else if (cursor_offset.
y - inner_size.
y >= scroll_y)
4116 scroll_y = cursor_offset.
y - inner_size.
y;
4117 draw_pos.
y += (draw_window->
Scroll.
y - scroll_y);
4118 draw_window->
Scroll.
y = scroll_y;
4126 if (render_selection)
4128 const ImWchar* text_selected_begin = text_begin +
ImMin(state->
Stb.select_start, state->
Stb.select_end);
4129 const ImWchar* text_selected_end = text_begin +
ImMax(state->
Stb.select_start, state->
Stb.select_end);
4132 float bg_offy_up = is_multiline ? 0.0f : -1.0f;
4133 float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
4134 ImVec2 rect_pos = draw_pos + select_start_offset - draw_scroll;
4135 for (
const ImWchar*
p = text_selected_begin;
p < text_selected_end; )
4137 if (rect_pos.
y > clip_rect.
w +
g.FontSize)
4139 if (rect_pos.
y < clip_rect.
y)
4143 while (
p < text_selected_end)
4150 if (rect_size.
x <= 0.0f) rect_size.
x =
IM_FLOOR(
g.Font->GetCharAdvance((
ImWchar)
' ') * 0.50f);
4151 ImRect rect(rect_pos +
ImVec2(0.0
f, bg_offy_up -
g.FontSize), rect_pos +
ImVec2(rect_size.
x, bg_offy_dn));
4156 rect_pos.
x = draw_pos.
x - draw_scroll.x;
4157 rect_pos.
y +=
g.FontSize;
4162 if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
4165 draw_window->
DrawList->
AddText(
g.Font,
g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ?
NULL : &clip_rect);
4172 bool cursor_is_visible = (!
g.IO.ConfigInputTextCursorBlink) || (state->
CursorAnim <= 0.0f) ||
ImFmod(state->
CursorAnim, 1.20f) <= 0.80f;
4173 ImVec2 cursor_screen_pos = draw_pos + cursor_offset - draw_scroll;
4174 ImRect cursor_screen_rect(cursor_screen_pos.
x, cursor_screen_pos.
y -
g.FontSize + 0.5f, cursor_screen_pos.
x + 1.0f, cursor_screen_pos.
y - 1.5f);
4175 if (cursor_is_visible && cursor_screen_rect.
Overlaps(clip_rect))
4180 g.PlatformImePos =
ImVec2(cursor_screen_pos.
x - 1.0f, cursor_screen_pos.
y -
g.FontSize);
4188 else if (!is_displaying_hint &&
g.ActiveId ==
id)
4189 buf_display_end = buf_display + state->
CurLenA;
4190 else if (!is_displaying_hint)
4191 buf_display_end = buf_display + strlen(buf_display);
4193 if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
4196 draw_window->
DrawList->
AddText(
g.Font,
g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ?
NULL : &clip_rect);
4207 if (is_password && !is_displaying_hint)
4211 if (
g.LogEnabled && !(is_password && !is_displaying_hint))
4214 if (label_size.
x > 0)
4222 return enter_pressed;
4224 return value_changed;
4261 const float w_inputs = w_full - w_button;
4263 g.NextItemData.ClearFlags();
4292 const int components =
alpha ? 4 : 3;
4295 float f[4] = { col[0], col[1], col[2],
alpha ? col[3] : 1.0f };
4302 if (memcmp(
g.ColorEditLastColor, col,
sizeof(
float) * 3) == 0)
4305 f[0] =
g.ColorEditLastHue;
4307 f[1] =
g.ColorEditLastSat;
4312 bool value_changed =
false;
4313 bool value_changed_as_float =
false;
4326 static const char*
ids[4] = {
"##X",
"##Y",
"##Z",
"##W" };
4327 static const char* fmt_table_int[3][4] =
4329 {
"%3d",
"%3d",
"%3d",
"%3d" },
4330 {
"R:%3d",
"G:%3d",
"B:%3d",
"A:%3d" },
4331 {
"H:%3d",
"S:%3d",
"V:%3d",
"A:%3d" }
4333 static const char* fmt_table_float[3][4] =
4335 {
"%0.3f",
"%0.3f",
"%0.3f",
"%0.3f" },
4336 {
"R:%0.3f",
"G:%0.3f",
"B:%0.3f",
"A:%0.3f" },
4337 {
"H:%0.3f",
"S:%0.3f",
"V:%0.3f",
"A:%0.3f" }
4341 for (
int n = 0;
n < components;
n++)
4350 value_changed |=
DragFloat(
ids[
n], &
f[
n], 1.0
f/255.0
f, 0.0
f, hdr ? 0.0
f : 1.0
f, fmt_table_float[fmt_idx][
n]);
4351 value_changed_as_float |= value_changed;
4355 value_changed |=
DragInt(
ids[
n], &
i[
n], 1.0
f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][
n]);
4366 ImFormatString(
buf,
IM_ARRAYSIZE(
buf),
"#%02X%02X%02X%02X",
ImClamp(
i[0],0,255),
ImClamp(
i[1],0,255),
ImClamp(
i[2],0,255),
ImClamp(
i[3],0,255));
4368 ImFormatString(
buf,
IM_ARRAYSIZE(
buf),
"#%02X%02X%02X",
ImClamp(
i[0],0,255),
ImClamp(
i[1],0,255),
ImClamp(
i[2],0,255));
4372 value_changed =
true;
4376 i[0] =
i[1] =
i[2] =
i[3] = 0;
4378 sscanf(
p,
"%02X%02X%02X%02X", (
unsigned int*)&
i[0], (
unsigned int*)&
i[1], (
unsigned int*)&
i[2], (
unsigned int*)&
i[3]);
4380 sscanf(
p,
"%02X%02X%02X", (
unsigned int*)&
i[0], (
unsigned int*)&
i[1], (
unsigned int*)&
i[2]);
4392 const ImVec4 col_v4(col[0], col[1], col[2],
alpha ? col[3] : 1.0
f);
4398 g.ColorPickerRef = col_v4;
4408 picker_active_window =
g.CurrentWindow;
4409 if (
label != label_display_end)
4417 value_changed |=
ColorPicker4(
"##picker", col, picker_flags, &
g.ColorPickerRef.x);
4430 if (value_changed && picker_active_window ==
NULL)
4432 if (!value_changed_as_float)
4433 for (
int n = 0;
n < 4;
n++)
4434 f[
n] =
i[
n] / 255.0
f;
4437 g.ColorEditLastHue =
f[0];
4438 g.ColorEditLastSat =
f[1];
4440 memcpy(
g.ColorEditLastColor,
f,
sizeof(
float) * 3);
4459 bool accepted_drag_drop =
false;
4462 memcpy((
float*)col, payload->Data,
sizeof(
float) * 3);
4463 value_changed = accepted_drag_drop =
true;
4467 memcpy((
float*)col, payload->Data,
sizeof(
float) * components);
4468 value_changed = accepted_drag_drop =
true;
4478 if (picker_active_window &&
g.ActiveId != 0 &&
g.ActiveIdWindow == picker_active_window)
4484 return value_changed;
4489 float col4[4] = { col[0], col[1], col[2], 1.0f };
4492 col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2];
4522 g.NextItemData.ClearFlags();
4549 float bars_width = square_sz;
4553 float bars_triangles_half_sz =
IM_FLOOR(bars_width * 0.20
f);
4555 float backup_initial_col[4];
4556 memcpy(backup_initial_col, col, components *
sizeof(
float));
4558 float wheel_thickness = sv_picker_size * 0.08f;
4559 float wheel_r_outer = sv_picker_size * 0.50f;
4560 float wheel_r_inner = wheel_r_outer - wheel_thickness;
4561 ImVec2 wheel_center(picker_pos.
x + (sv_picker_size + bars_width)*0.5f, picker_pos.
y + sv_picker_size*0.5f);
4564 float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027
f);
4566 ImVec2 triangle_pb =
ImVec2(triangle_r * -0.5
f, triangle_r * -0.866025
f);
4567 ImVec2 triangle_pc =
ImVec2(triangle_r * -0.5
f, triangle_r * +0.866025
f);
4569 float H = col[0],
S = col[1], V = col[2];
4570 float R = col[0], G = col[1], B = col[2];
4575 if (memcmp(
g.ColorEditLastColor, col,
sizeof(
float) * 3) == 0)
4578 H =
g.ColorEditLastHue;
4580 S =
g.ColorEditLastSat;
4588 bool value_changed =
false, value_changed_h =
false, value_changed_sv =
false;
4597 ImVec2 initial_off =
g.IO.MouseClickedPos[0] - wheel_center;
4598 ImVec2 current_off =
g.IO.MousePos - wheel_center;
4600 if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1))
4606 value_changed = value_changed_h =
true;
4613 ImVec2 current_off_unrotated =
ImRotate(current_off, cos_hue_angle, sin_hue_angle);
4615 current_off_unrotated =
ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);
4620 value_changed = value_changed_sv =
true;
4634 value_changed = value_changed_sv =
true;
4645 value_changed = value_changed_h =
true;
4657 value_changed =
true;
4671 if (
label != label_display_end)
4688 if (ref_col !=
NULL)
4692 if (
ColorButton(
"##original", ref_col_v4, (
flags & sub_flags_to_forward),
ImVec2(square_sz * 3, square_sz * 2)))
4694 memcpy(col, ref_col, components *
sizeof(
float));
4695 value_changed =
true;
4703 if (value_changed_h || value_changed_sv)
4708 g.ColorEditLastHue =
H;
4709 g.ColorEditLastSat =
S;
4710 memcpy(
g.ColorEditLastColor, col,
sizeof(
float) * 3);
4721 bool value_changed_fix_hue_wrap =
false;
4724 PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.
x);
4732 value_changed_fix_hue_wrap = (
g.ActiveId != 0 && !
g.ActiveIdAllowOverlap);
4733 value_changed =
true;
4745 float new_H, new_S, new_V;
4747 if (new_H <= 0 && H > 0)
4749 if (new_V <= 0 && V != new_V)
4751 else if (new_S <= 0)
4764 if (memcmp(
g.ColorEditLastColor, col,
sizeof(
float) * 3) == 0)
4767 H =
g.ColorEditLastHue;
4769 S =
g.ColorEditLastSat;
4784 const ImU32 col_midgrey =
IM_COL32(128,128,128,style_alpha8);
4785 const ImU32 col_hues[6 + 1] = {
IM_COL32(255,0,0,style_alpha8),
IM_COL32(255,255,0,style_alpha8),
IM_COL32(0,255,0,style_alpha8),
IM_COL32(0,255,255,style_alpha8),
IM_COL32(0,0,255,style_alpha8),
IM_COL32(255,0,255,style_alpha8),
IM_COL32(255,0,0,style_alpha8) };
4796 const float aeps = 0.5f / wheel_r_outer;
4797 const int segment_per_arc =
ImMax(4, (
int)wheel_r_outer / 12);
4798 for (
int n = 0;
n < 6;
n++)
4800 const float a0 = (
n) /6.0
f * 2.0
f *
IM_PI - aeps;
4801 const float a1 = (
n+1.0f)/6.0
f * 2.0
f *
IM_PI + aeps;
4803 draw_list->
PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
4804 draw_list->
PathStroke(col_white,
false, wheel_thickness);
4808 ImVec2 gradient_p0(wheel_center.
x +
ImCos(a0) * wheel_r_inner, wheel_center.
y +
ImSin(a0) * wheel_r_inner);
4809 ImVec2 gradient_p1(wheel_center.
x +
ImCos(a1) * wheel_r_inner, wheel_center.
y +
ImSin(a1) * wheel_r_inner);
4816 ImVec2 hue_cursor_pos(wheel_center.
x + cos_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f, wheel_center.
y + sin_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f);
4817 float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
4818 int hue_cursor_segments =
ImClamp((
int)(hue_cursor_rad / 1.4
f), 9, 32);
4819 draw_list->
AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
4820 draw_list->
AddCircle(hue_cursor_pos, hue_cursor_rad+1, col_midgrey, hue_cursor_segments);
4821 draw_list->
AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
4824 ImVec2 tra = wheel_center +
ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
4825 ImVec2 trb = wheel_center +
ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
4826 ImVec2 trc = wheel_center +
ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
4829 draw_list->
PrimVtx(tra, uv_white, hue_color32);
4830 draw_list->
PrimVtx(trb, uv_white, hue_color32);
4831 draw_list->
PrimVtx(trc, uv_white, col_white);
4832 draw_list->
PrimVtx(tra, uv_white, 0);
4833 draw_list->
PrimVtx(trb, uv_white, col_black);
4834 draw_list->
PrimVtx(trc, uv_white, 0);
4835 draw_list->
AddTriangle(tra, trb, trc, col_midgrey, 1.5
f);
4841 draw_list->
AddRectFilledMultiColor(picker_pos, picker_pos +
ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white);
4845 sv_cursor_pos.
y =
ImClamp(
IM_ROUND(picker_pos.
y +
ImSaturate(1 - V) * sv_picker_size), picker_pos.
y + 2, picker_pos.
y + sv_picker_size - 2);
4848 for (
int i = 0;
i < 6; ++
i)
4849 draw_list->
AddRectFilledMultiColor(
ImVec2(bar0_pos_x, picker_pos.
y +
i * (sv_picker_size / 6)),
ImVec2(bar0_pos_x + bars_width, picker_pos.
y + (
i + 1) * (sv_picker_size / 6)), col_hues[
i], col_hues[
i], col_hues[
i + 1], col_hues[
i + 1]);
4850 float bar0_line_y =
IM_ROUND(picker_pos.
y +
H * sv_picker_size);
4856 float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
4857 draw_list->
AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12);
4858 draw_list->
AddCircle(sv_cursor_pos, sv_cursor_rad+1, col_midgrey, 12);
4859 draw_list->
AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12);
4865 ImRect bar1_bb(bar1_pos_x, picker_pos.
y, bar1_pos_x + bars_width, picker_pos.
y + sv_picker_size);
4868 float bar1_line_y =
IM_ROUND(picker_pos.
y + (1.0f -
alpha) * sv_picker_size);
4875 if (value_changed && memcmp(backup_initial_col, col, components *
sizeof(
float)) == 0)
4876 value_changed =
false;
4882 return value_changed;
4899 size.x = default_size;
4901 size.y = default_size;
4903 ItemSize(bb, (
size.y >= default_size) ?
g.Style.FramePadding.y : 0.0f);
4917 ImVec4 col_rgb_without_alpha(col_rgb.
x, col_rgb.
y, col_rgb.
z, 1.0f);
4919 float rounding =
ImMin(
g.Style.FrameRounding, grid_step * 0.5f);
4937 if (col_source.
w < 1.0f)
4945 if (
g.Style.FrameBorderSize > 0.0f)
4988 g.ColorEditOptions =
flags;
4998 if (text_end > text)
5004 ImVec2 sz(
g.FontSize * 3 +
g.Style.FramePadding.y * 2,
g.FontSize * 3 +
g.Style.FramePadding.y * 2);
5012 Text(
"#%02X%02X%02X\nR: %d, G: %d, B: %d\n(%.3f, %.3f, %.3f)", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]);
5014 Text(
"#%02X%02X%02X%02X\nR:%d, G:%d, B:%d, A:%d\n(%.3f, %.3f, %.3f, %.3f)", cr, cg, cb, ca, cr, cg, cb, ca, col[0], col[1], col[2], col[3]);
5019 Text(
"H: %.3f, S: %.3f, V: %.3f", col[0], col[1], col[2]);
5021 Text(
"H: %.3f, S: %.3f, V: %.3f, A: %.3f", col[0], col[1], col[2], col[3]);
5030 if ((!allow_opt_inputs && !allow_opt_datatype) || !
BeginPopup(
"context"))
5034 if (allow_opt_inputs)
5040 if (allow_opt_datatype)
5047 if (allow_opt_inputs || allow_opt_datatype)
5073 g.ColorEditOptions = opts;
5081 if ((!allow_opt_picker && !allow_opt_alpha_bar) || !
BeginPopup(
"context"))
5084 if (allow_opt_picker)
5088 for (
int picker_type = 0; picker_type < 2; picker_type++)
5097 if (
Selectable(
"##selectable",
false, 0, picker_size))
5102 ColorPicker4(
"##dummypicker", &dummy_ref_col.
x, picker_flags);
5107 if (allow_opt_alpha_bar)
5230 is_open =
g.NextItemData.OpenVal;
5231 storage->
SetInt(
id, is_open);
5236 const int stored_value = storage->
GetInt(
id, -1);
5237 if (stored_value == -1)
5239 is_open =
g.NextItemData.OpenVal;
5240 storage->
SetInt(
id, is_open);
5244 is_open = stored_value != 0;
5291 const float text_offset_x =
g.FontSize + (display_frame ? padding.
x*3 : padding.
x*2);
5293 const float text_width =
g.FontSize + (label_size.
x > 0.0f ? label_size.
x + padding.
x*2 : 0.0f);
5298 ImRect interact_bb = frame_bb;
5310 bool item_add =
ItemAdd(interact_bb,
id);
5332 const float arrow_hit_x2 = (text_pos.
x - text_offset_x) + (
g.FontSize + padding.
x * 2.0f) + style.
TouchExtraPadding.
x;
5333 const bool is_mouse_x_over_arrow = (
g.IO.MousePos.x >= arrow_hit_x1 &&
g.IO.MousePos.x < arrow_hit_x2);
5334 if (window !=
g.HoveredWindow || !is_mouse_x_over_arrow)
5356 const bool was_selected = selected;
5359 bool pressed =
ButtonBehavior(interact_bb,
id, &hovered, &held, button_flags);
5360 bool toggled =
false;
5368 toggled |= is_mouse_x_over_arrow && !
g.NavDisableMouseHover;
5371 if (
g.DragDropActive && is_open)
5375 if (
g.NavId ==
id &&
g.NavMoveRequest &&
g.NavMoveDir ==
ImGuiDir_Left && is_open)
5380 if (
g.NavId ==
id &&
g.NavMoveRequest &&
g.NavMoveDir ==
ImGuiDir_Right && !is_open)
5397 if (selected != was_selected)
5414 text_pos.
x -= text_offset_x;
5420 const char log_prefix[] =
"\n##";
5421 const char log_suffix[] =
"##";
5434 if (hovered || selected)
5460 PushID(str_id ? str_id :
"#TreePush");
5468 PushID(ptr_id ? ptr_id : (
const void*)
"#TreePush");
5505 return g.
FontSize + (
g.Style.FramePadding.x * 2.0f);
5512 if (
g.CurrentWindow->SkipItems)
5515 g.NextItemData.OpenVal = is_open;
5536 if (p_open && !*p_open)
5551 float button_size =
g.FontSize;
5587 ImVec2 size(size_arg.
x != 0.0f ? size_arg.
x : label_size.
x, size_arg.
y != 0.0f ? size_arg.
y : label_size.
y);
5599 const ImVec2 text_min = pos;
5603 ImRect bb_enlarged(min_x, pos.
y, text_max.
x, text_max.
y);
5606 const float spacing_L =
IM_FLOOR(spacing_x * 0.50
f);
5607 const float spacing_U =
IM_FLOOR(spacing_y * 0.50
f);
5608 bb_enlarged.
Min.
x -= spacing_L;
5609 bb_enlarged.
Min.
y -= spacing_U;
5610 bb_enlarged.
Max.
x += (spacing_x - spacing_L);
5611 bb_enlarged.
Max.
y += (spacing_y - spacing_U);
5620 item_add =
ItemAdd(bb_enlarged,
id);
5625 item_add =
ItemAdd(bb_enlarged,
id);
5646 const bool was_selected = selected;
5648 bool pressed =
ButtonBehavior(bb_enlarged,
id, &hovered, &held, button_flags);
5653 if (!
g.NavDisableMouseHover &&
g.NavWindow == window &&
g.NavLayer == window->
DC.
NavLayerCurrent)
5655 g.NavDisableHighlight =
true;
5666 if (selected != was_selected)
5672 if (hovered || selected)
5698 *p_selected = !*p_selected;
5735 g.NextItemData.ClearFlags();
5745 if (label_size.
x > 0)
5759 if (height_in_items < 0)
5760 height_in_items =
ImMin(items_count, 7);
5762 float height_in_items_f = (height_in_items < items_count) ? (height_in_items + 0.25
f) : (height_in_items + 0.00f);
5788 bool ImGui::ListBox(
const char*
label,
int* current_item,
const char*
const items[],
int items_count,
int height_items)
5791 return value_changed;
5794 bool ImGui::ListBox(
const char*
label,
int* current_item,
bool (*items_getter)(
void*,
int,
const char**),
void*
data,
int items_count,
int height_in_items)
5801 bool value_changed =
false;
5803 while (clipper.Step())
5804 for (
int i = clipper.DisplayStart;
i < clipper.DisplayEnd;
i++)
5806 const bool item_selected = (
i == *current_item);
5807 const char* item_text;
5808 if (!items_getter(
data,
i, &item_text))
5809 item_text =
"*Unknown item*";
5815 value_changed =
true;
5825 return value_changed;
5836 void ImGui::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 frame_size)
5847 if (frame_size.
x == 0.0f)
5849 if (frame_size.
y == 0.0f)
5856 if (!
ItemAdd(total_bb, 0, &frame_bb))
5861 if (scale_min == FLT_MAX || scale_max == FLT_MAX)
5863 float v_min = FLT_MAX;
5864 float v_max = -FLT_MAX;
5865 for (
int i = 0;
i < values_count;
i++)
5867 const float v = values_getter(
data,
i);
5873 if (scale_min == FLT_MAX)
5875 if (scale_max == FLT_MAX)
5882 if (values_count >= values_count_min)
5889 if (hovered && inner_bb.
Contains(
g.IO.MousePos))
5891 const float t =
ImClamp((
g.IO.MousePos.x - inner_bb.
Min.
x) / (inner_bb.
Max.
x - inner_bb.
Min.
x), 0.0f, 0.9999f);
5892 const int v_idx = (int)(t * item_count);
5893 IM_ASSERT(v_idx >= 0 && v_idx < values_count);
5895 const float v0 = values_getter(
data, (v_idx + values_offset) % values_count);
5896 const float v1 = values_getter(
data, (v_idx + 1 + values_offset) % values_count);
5904 const float t_step = 1.0f / (float)res_w;
5905 const float inv_scale = (scale_min == scale_max) ? 0.0
f : (1.0
f / (scale_max - scale_min));
5907 float v0 = values_getter(
data, (0 + values_offset) % values_count);
5910 float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f);
5915 for (
int n = 0;
n < res_w;
n++)
5917 const float t1 = t0 + t_step;
5918 const int v1_idx = (int)(t0 * item_count + 0.5
f);
5919 IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
5920 const float v1 = values_getter(
data, (v1_idx + values_offset + 1) % values_count);
5928 window->
DrawList->
AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
5932 if (pos1.
x >= pos0.
x + 2.0f)
5946 if (label_size.
x > 0.0f)
5961 const float v = *(
const float*)(
const void*)((
const unsigned char*)plot_data->
Values + (
size_t)
idx * plot_data->
Stride);
5971 void ImGui::PlotLines(
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)
6040 memset(
Pos, 0,
sizeof(
Pos));
6132 g.NavDisableHighlight =
true;
6163 g.NextWindowData.MenuBarOffsetMinVal =
ImVec2(0.0
f, 0.0
f);
6179 if (
g.CurrentWindow ==
g.NavWindow &&
g.NavLayer == 0 && !
g.NavAnyRequest)
6204 if (
g.MenusIdSubmittedThisFrame.contains(
id))
6209 g.NextWindowData.ClearFlags();
6210 return menu_is_open;
6214 g.MenusIdSubmittedThisFrame.push_back(
id);
6220 if (menuset_is_open)
6221 g.NavWindow = window;
6235 float w = label_size.
x;
6254 if (menuset_is_open)
6255 g.NavWindow = backed_nav_window;
6257 bool want_open =
false;
6258 bool want_close =
false;
6263 bool moving_toward_other_child_menu =
false;
6265 ImGuiWindow* child_menu_window = (
g.BeginPopupStack.Size <
g.OpenPopupStack.Size &&
g.OpenPopupStack[
g.BeginPopupStack.Size].SourceWindow == window) ?
g.OpenPopupStack[
g.BeginPopupStack.Size].Window :
NULL;
6269 ImRect next_window_rect = child_menu_window->
Rect();
6270 ImVec2 ta =
g.IO.MousePos -
g.IO.MouseDelta;
6274 ta.
x += (window->
Pos.
x < child_menu_window->
Pos.
x) ? -0.5
f : +0.5
f;
6275 tb.
y = ta.
y +
ImMax((tb.
y - extra) - ta.
y, -100.0f);
6276 tc.
y = ta.
y +
ImMin((tc.
y + extra) - ta.
y, +100.0f);
6280 if (menu_is_open && !hovered &&
g.HoveredWindow == window &&
g.HoveredIdPreviousFrame != 0 &&
g.HoveredIdPreviousFrame !=
id && !moving_toward_other_child_menu)
6283 if (!menu_is_open && hovered && pressed)
6285 else if (!menu_is_open && hovered && !moving_toward_other_child_menu)
6288 if (
g.NavActivateId ==
id)
6290 want_close = menu_is_open;
6291 want_open = !menu_is_open;
6302 if (menu_is_open && pressed && menuset_is_open)
6305 want_open = menu_is_open =
false;
6307 else if (pressed || (hovered && menuset_is_open && !menu_is_open))
6311 else if (
g.NavId ==
id &&
g.NavMoveRequest &&
g.NavMoveDir ==
ImGuiDir_Down)
6325 if (!menu_is_open && want_open &&
g.OpenPopupStack.Size >
g.BeginPopupStack.Size)
6332 menu_is_open |= want_open;
6343 g.NextWindowData.ClearFlags();
6346 return menu_is_open;
6384 float w = label_size.
x;
6400 if (shortcut_w > 0.0
f)
6419 *p_selected = !*p_selected;
6474 return (
int)(
a->Offset -
b->Offset);
6486 if (
g.TabBars.Contains(tab_bar))
6517 g.CurrentTabBar = tab_bar;
6536 tab_bar->
BarRect = tab_bar_bb;
6565 if (tab_bar ==
NULL)
6583 g.CurrentTabBarStack.pop_back();
6596 for (
int tab_src_n = 0; tab_src_n < tab_bar->
Tabs.
Size; tab_src_n++)
6605 if (tab_dst_n != tab_src_n)
6606 tab_bar->
Tabs[tab_dst_n] = tab_bar->
Tabs[tab_src_n];
6609 if (tab_bar->
Tabs.
Size != tab_dst_n)
6613 ImGuiID scroll_track_selected_tab_id = 0;
6628 if (tab2_order >= 0 && tab2_order < tab_bar->Tabs.Size)
6635 scroll_track_selected_tab_id = tab2->
ID;
6646 if (tab_list_popup_button)
6648 scroll_track_selected_tab_id = tab_bar->
SelectedTabId = tab_to_select->ID;
6651 g.ShrinkWidthBuffer.resize(tab_bar->
Tabs.
Size);
6652 float width_total_contents = 0.0f;
6654 bool found_selected_tab_id =
false;
6655 for (
int tab_n = 0; tab_n < tab_bar->
Tabs.
Size; tab_n++)
6661 most_recently_selected_tab = tab;
6663 found_selected_tab_id =
true;
6668 const char* tab_name = tab_bar->
GetTabName(tab);
6672 width_total_contents += (tab_n > 0 ?
g.Style.ItemInnerSpacing.x : 0.0f) + tab->
ContentWidth;
6675 g.ShrinkWidthBuffer[tab_n].Index = tab_n;
6680 const float initial_offset_x = 0.0f;
6682 float width_excess = (width_avail < width_total_contents) ? (width_total_contents - width_avail) : 0.0f;
6686 ShrinkWidths(
g.ShrinkWidthBuffer.Data,
g.ShrinkWidthBuffer.Size, width_excess);
6687 for (
int tab_n = 0; tab_n < tab_bar->
Tabs.
Size; tab_n++)
6688 tab_bar->
Tabs[
g.ShrinkWidthBuffer[tab_n].Index].Width =
IM_FLOOR(
g.ShrinkWidthBuffer[tab_n].Width);
6693 for (
int tab_n = 0; tab_n < tab_bar->
Tabs.
Size; tab_n++)
6702 float offset_x = initial_offset_x;
6703 float offset_x_ideal = offset_x;
6705 for (
int tab_n = 0; tab_n < tab_bar->
Tabs.
Size; tab_n++)
6709 if (scroll_track_selected_tab_id == 0 &&
g.NavJustMovedToId == tab->
ID)
6710 scroll_track_selected_tab_id = tab->
ID;
6711 offset_x += tab->
Width +
g.Style.ItemInnerSpacing.x;
6712 offset_x_ideal += tab->
ContentWidth +
g.Style.ItemInnerSpacing.x;
6714 tab_bar->
OffsetMax =
ImMax(offset_x -
g.Style.ItemInnerSpacing.x, 0.0f);
6719 if (scrolling_buttons)
6721 scroll_track_selected_tab_id = tab_bar->
SelectedTabId = tab_to_select->ID;
6724 if (found_selected_tab_id ==
false)
6727 scroll_track_selected_tab_id = tab_bar->
SelectedTabId = most_recently_selected_tab->
ID;
6734 if (scroll_track_selected_tab_id)
6784 if (tab_bar->
Tabs[
n].ID == tab_id)
6785 return &tab_bar->
Tabs[
n];
6819 return ImMax(scrolling, 0.0
f);
6827 float tab_x1 = tab->
Offset + (order > 0 ? -margin : 0.0f);
6828 float tab_x2 = tab->
Offset + tab->
Width + (order + 1 < tab_bar->
Tabs.
Size ? margin : 1.0f);
6855 const ImVec2 arrow_button_size(
g.FontSize - 2.0f,
g.FontSize +
g.Style.FramePadding.y * 2.0f);
6856 const float scrolling_buttons_width = arrow_button_size.
x * 2.0f;
6870 arrow_col.
w *= 0.5f;
6874 const float backup_repeat_delay =
g.IO.KeyRepeatDelay;
6875 const float backup_repeat_rate =
g.IO.KeyRepeatRate;
6876 g.IO.KeyRepeatDelay = 0.250f;
6877 g.IO.KeyRepeatRate = 0.200f;
6885 g.IO.KeyRepeatRate = backup_repeat_rate;
6886 g.IO.KeyRepeatDelay = backup_repeat_delay;
6891 if (select_dir != 0)
6894 int selected_order = tab_bar->
GetTabOrder(tab_item);
6895 int target_order = selected_order + select_dir;
6896 tab_to_select = &tab_bar->
Tabs[(target_order >= 0 && target_order < tab_bar->
Tabs.
Size) ? target_order : selected_order];
6899 tab_bar->
BarRect.
Max.
x -= scrolling_buttons_width + 1.0f;
6901 return tab_to_select;
6910 const float tab_list_popup_button_width =
g.FontSize +
g.Style.FramePadding.y;
6913 tab_bar->
BarRect.
Min.
x += tab_list_popup_button_width;
6916 arrow_col.
w *= 0.5f;
6925 for (
int tab_n = 0; tab_n < tab_bar->
Tabs.
Size; tab_n++)
6928 const char* tab_name = tab_bar->
GetTabName(tab);
6930 tab_to_select = tab;
6936 return tab_to_select;
6959 if (tab_bar ==
NULL)
6961 IM_ASSERT_USER_ERROR(tab_bar,
"BeginTabItem() Needs to be called between BeginTabBar() and EndTabBar()!");
6981 if (tab_bar ==
NULL)
6983 IM_ASSERT(tab_bar !=
NULL &&
"Needs to be called between BeginTabBar() and EndTabBar()!");
7007 if (p_open && !*p_open)
7018 else if (p_open ==
NULL)
7026 bool tab_is_new =
false;
7065 if (tab_contents_visible)
7069 if (!tab_contents_visible && tab_bar->
SelectedTabId == 0 && tab_bar_appearing)
7071 tab_contents_visible =
true;
7073 if (tab_appearing && !(tab_bar_appearing && !tab_is_new))
7078 return tab_contents_visible;
7107 return tab_contents_visible;
7112 if (
g.DragDropActive)
7115 bool pressed =
ButtonBehavior(bb,
id, &hovered, &held, button_flags);
7118 hovered |= (
g.HoveredId ==
id);
7130 if (
g.IO.MouseDelta.x < 0.0f &&
g.IO.MousePos.x < bb.
Min.
x)
7135 else if (
g.IO.MouseDelta.x > 0.0f &&
g.IO.MousePos.x > bb.
Max.
x)
7168 const ImGuiID close_button_id = p_open ? window->
GetID((
void*)((intptr_t)
id + 1)) : 0;
7170 if (just_closed && p_open !=
NULL)
7183 if (
g.HoveredId ==
id && !held &&
g.HoveredIdNotActiveTimer > 0.50f &&
IsItemHovered())
7187 return tab_contents_visible;
7196 if (is_within_manual_tab_bar)
7209 ImVec2 size =
ImVec2(label_size.
x +
g.Style.FramePadding.x, label_size.
y +
g.Style.FramePadding.y * 2.0f);
7210 if (has_close_button)
7211 size.x +=
g.Style.FramePadding.x + (
g.Style.ItemInnerSpacing.x +
g.FontSize);
7213 size.x +=
g.Style.FramePadding.x + 1.0f;
7224 const float rounding =
ImMax(0.0
f,
ImMin(
g.Style.TabRounding,
width * 0.5f - 1.0f));
7225 const float y1 = bb.
Min.
y + 1.0f;
7226 const float y2 = bb.
Max.
y - 1.0f;
7232 if (
g.Style.TabBorderSize > 0.0f)
7252 const char* TAB_UNSAVED_MARKER =
"*";
7253 ImRect text_pixel_clip_bb(bb.
Min.
x + frame_padding.
x, bb.
Min.
y + frame_padding.
y, bb.
Max.
x - frame_padding.
x, bb.
Max.
y);
7260 ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
7267 bool close_button_pressed =
false;
7268 bool close_button_visible =
false;
7269 if (close_button_id != 0)
7270 if (
g.HoveredId == tab_id ||
g.HoveredId == close_button_id ||
g.ActiveId == close_button_id)
7271 close_button_visible =
true;
7272 if (close_button_visible)
7275 const float close_button_sz =
g.FontSize;
7278 close_button_pressed =
true;
7284 close_button_pressed =
true;
7286 text_pixel_clip_bb.
Max.
x -= close_button_sz;
7289 float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.
Max.
x : bb.
Max.
x - 1.0f;
7292 return close_button_pressed;
7362 if (columns ==
NULL)
7365 if (column_index < 0)
7366 column_index = columns->
Current;
7369 const float t = columns->
Columns[column_index].OffsetNorm;
7376 if (column_index < 0)
7377 column_index = columns->
Current;
7381 offset_norm = columns->
Columns[column_index + 1].OffsetNormBeforeResize - columns->
Columns[column_index].OffsetNormBeforeResize;
7383 offset_norm = columns->
Columns[column_index + 1].OffsetNorm - columns->
Columns[column_index].OffsetNorm;
7392 if (columns ==
NULL)
7395 if (column_index < 0)
7396 column_index = columns->
Current;
7407 if (column_index < 0)
7408 column_index = columns->
Current;
7428 if (column_index < 0)
7429 column_index = columns->
Current;
7437 if (column_index < 0)
7438 column_index = columns->
Current;
7449 if (columns->
Count == 1)
7462 if (columns->
Count == 1)
7487 PushID(0x11223347 + (str_id ? 0 : columns_count));
7488 ImGuiID id = window->
GetID(str_id ? str_id :
"columns");
7499 IM_ASSERT(columns_count >= 1 && columns_count <= 64);
7507 columns->
Count = columns_count;
7518 const float column_padding =
g.Style.ItemSpacing.x;
7521 const float max_2 = window->
WorkRect.
Max.
x + half_clip_extend_x;
7535 for (
int n = 0;
n < columns_count + 1;
n++)
7543 for (
int n = 0;
n < columns_count;
n++)
7553 if (columns->
Count > 1)
7563 float width = offset_1 - offset_0;
7579 if (columns->
Count == 1)
7588 const float column_padding =
g.Style.ItemSpacing.x;
7616 float width = offset_1 - offset_0;
7629 if (columns->
Count > 1)
7643 bool is_being_resized =
false;
7649 int dragging_column = -1;
7650 for (
int n = 1;
n < columns->
Count;
n++)
7658 if (
IsClippedEx(column_hit_rect, column_id,
false))
7661 bool hovered =
false, held =
false;
7665 if (hovered || held)
7668 dragging_column =
n;
7678 if (dragging_column != -1)
7681 for (
int n = 0;
n < columns->
Count + 1;
n++)
7682 columns->
Columns[
n].OffsetNormBeforeResize = columns->
Columns[
n].OffsetNorm;
7708 if (columns !=
NULL)
7711 if (columns_count != 1)
7717 #endif // #ifndef IMGUI_DISABLE