30 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
31 #define _CRT_SECURE_NO_WARNINGS
35 #ifndef IMGUI_DEFINE_MATH_OPERATORS
36 #define IMGUI_DEFINE_MATH_OPERATORS
41 #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
49 #pragma warning (disable: 4127) // condition expression is constant
50 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
55 #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.
56 #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
57 #elif defined(__GNUC__)
58 #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
60 #pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
127 const char* text_begin = text;
128 if (text_end ==
NULL)
129 text_end = text + strlen(text);
133 const bool wrap_enabled = wrap_pos_x >= 0.0f;
134 if (text_end - text > 2000 && !wrap_enabled)
141 const char* line = text;
146 if (text_pos.
y <= clip_rect.
Max.
y)
153 int lines_skippable = (int)((clip_rect.
Min.
y - text_pos.
y) / line_height);
154 if (lines_skippable > 0)
156 int lines_skipped = 0;
157 while (line < text_end && lines_skipped < lines_skippable)
159 const char* line_end = (
const char*)memchr(line,
'\n', text_end - line);
165 pos.
y += lines_skipped * line_height;
172 ImRect line_rect(pos, pos +
ImVec2(FLT_MAX, line_height));
173 while (line < text_end)
178 const char* line_end = (
const char*)memchr(line,
'\n', text_end - line);
182 text_size.
x =
ImMax(text_size.
x, line_size.
x);
185 line_rect.
Min.
y += line_height;
186 line_rect.
Max.
y += line_height;
187 pos.
y += line_height;
191 int lines_skipped = 0;
192 while (line < text_end)
194 const char* line_end = (
const char*)memchr(line,
'\n', text_end - line);
200 pos.
y += lines_skipped * line_height;
203 text_size.
y += (pos - text_pos).y;
206 ImRect bb(text_pos, text_pos + text_size);
216 ImRect bb(text_pos, text_pos + text_size);
320 const char* value_text_begin = &g.
TempBuffer[0];
323 if (label_size.
x > 0.0f)
387 if (out_hovered) *out_hovered =
false;
388 if (out_held) *out_held =
false;
401 #ifdef IMGUI_ENABLE_TEST_ENGINE
403 ImGuiTestEngineHook_ItemAdd(&g, bb,
id);
406 bool pressed =
false;
486 if (nav_activated_by_code || nav_activated_by_inputs)
488 if (nav_activated_by_code || nav_activated_by_inputs || g.
ActiveId ==
id)
528 if (out_hovered) *out_hovered = hovered;
529 if (out_held) *out_held = held;
550 const ImRect bb(pos, pos + size);
577 return ButtonEx(label, size_arg, 0);
600 IM_ASSERT(size_arg.
x != 0.0f && size_arg.
y != 0.0f);
659 bool is_clipped = !
ItemAdd(bb,
id);
671 float cross_extent = (radius * 0.7071f) - 1.0
f;
714 const ImGuiID id = window->
GetID(horizontal ?
"#SCROLLX" :
"#SCROLLY");
718 float other_scrollbar_size_w = other_scrollbar ? style.
ScrollbarSize : 0.0f;
729 int window_rounding_corners;
739 float scroll_v = horizontal ? window->
Scroll.
x : window->
Scroll.
y;
740 float win_size_avail_v = (horizontal ? window->
SizeFull.
x : window->
SizeFull.
y) - other_scrollbar_size_w;
746 const float win_size_v =
ImMax(
ImMax(win_size_contents_v, win_size_avail_v), 1.0
f);
747 const float grab_h_pixels =
ImClamp(scrollbar_size_v * (win_size_avail_v / win_size_v), style.
GrabMinSize, scrollbar_size_v);
748 const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
752 bool hovered =
false;
753 const bool previously_held = (g.
ActiveId ==
id);
756 float scroll_max =
ImMax(1.0
f, win_size_contents_v - win_size_avail_v);
757 float scroll_ratio =
ImSaturate(scroll_v / scroll_max);
758 float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
759 if (held && grab_h_norm < 1.0
f)
761 float scrollbar_pos_v = horizontal ? bb.
Min.
x : bb.
Min.
y;
766 const float clicked_v_norm =
ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
769 bool seek_absolute =
false;
770 if (!previously_held)
773 if (clicked_v_norm >= grab_v_norm && clicked_v_norm <= grab_v_norm + grab_h_norm)
775 *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f;
779 seek_absolute =
true;
780 *click_delta_to_grab_center_v = 0.0f;
786 const float scroll_v_norm =
ImSaturate((clicked_v_norm - *click_delta_to_grab_center_v - grab_h_norm*0.5
f) / (1.0
f - grab_h_norm));
787 scroll_v = (float)(
int)(0.5f + scroll_v_norm * scroll_max);
794 scroll_ratio =
ImSaturate(scroll_v / scroll_max);
795 grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
799 *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f;
819 if (border_col.
w > 0.0f)
825 if (border_col.
w > 0.0f)
851 PushID((
void*)(intptr_t)user_texture_id);
855 const ImVec2 padding = (frame_padding >= 0) ?
ImVec2((
float)frame_padding, (float)frame_padding) : style.
FramePadding;
890 ImRect total_bb = check_bb;
891 if (label_size.
x > 0)
894 if (label_size.
x > 0)
916 const float pad =
ImMax(1.0
f, (
float)(
int)(check_sz / 6.0
f));
922 if (label_size.
x > 0.0f)
931 bool v = ((*flags & flags_value) == flags_value);
936 *flags |= flags_value;
938 *flags &= ~flags_value;
958 ImRect total_bb = check_bb;
959 if (label_size.
x > 0)
962 if (label_size.
x > 0)
965 total_bb.
Add(text_bb);
972 center.
x = (float)(
int)center.
x + 0.5f;
973 center.
y = (float)(
int)center.
y + 0.5f;
974 const float radius = check_bb.
GetHeight() * 0.5f;
986 const float pad =
ImMax(1.0
f, (
float)(
int)(check_sz / 6.0
f));
998 if (label_size.
x > 0.0f)
1006 const bool pressed =
RadioButton(label, *v == v_button);
1036 char overlay_buf[32];
1040 overlay = overlay_buf;
1044 if (overlay_size.
x > 0.0f)
1045 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);
1149 float x1 = window->
Pos.
x;
1150 float x2 = window->
Pos.
x + window->
Size.
x;
1202 bool item_add =
ItemAdd(bb,
id);
1221 float mouse_delta = (axis ==
ImGuiAxis_Y) ? mouse_delta_2d.
y : mouse_delta_2d.
x;
1224 float size_1_maximum_delta =
ImMax(0.0
f, *size1 - min_size1);
1225 float size_2_maximum_delta =
ImMax(0.0
f, *size2 - min_size2);
1226 if (mouse_delta < -size_1_maximum_delta)
1227 mouse_delta = -size_1_maximum_delta;
1228 if (mouse_delta > size_2_maximum_delta)
1229 mouse_delta = size_2_maximum_delta;
1232 if (mouse_delta != 0.0
f)
1234 if (mouse_delta < 0.0
f)
1235 IM_ASSERT(*size1 + mouse_delta >= min_size1);
1236 if (mouse_delta > 0.0
f)
1237 IM_ASSERT(*size2 - mouse_delta >= min_size2);
1238 *size1 += mouse_delta;
1239 *size2 -= mouse_delta;
1263 if (items_count <= 0)
1290 if (!
ItemAdd(total_bb,
id, &frame_bb))
1310 if (label_size.
x > 0)
1324 if (backup_next_window_size_constraint)
1334 int popup_max_height_in_items = -1;
1346 if (popup_window->WasActive)
1359 bool ret =
Begin(name,
NULL, window_flags);
1378 const char*
const* items = (
const char*
const*)data;
1380 *out_text = items[idx];
1388 const char* items_separated_by_zeros = (
const char*)data;
1389 int items_count = 0;
1390 const char* p = items_separated_by_zeros;
1393 if (idx == items_count)
1406 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)
1411 const char* preview_value =
NULL;
1412 if (*current_item >= 0 && *current_item < items_count)
1413 items_getter(data, *current_item, &preview_value);
1424 bool value_changed =
false;
1425 for (
int i = 0; i < items_count; i++)
1427 PushID((
void*)(intptr_t)i);
1428 const bool item_selected = (i == *current_item);
1429 const char* item_text;
1430 if (!items_getter(data, i, &item_text))
1431 item_text =
"*Unknown item*";
1434 value_changed =
true;
1443 return value_changed;
1447 bool ImGui::Combo(
const char* label,
int* current_item,
const char*
const items[],
int items_count,
int height_in_items)
1449 const bool value_changed =
Combo(label, current_item,
Items_ArrayGetter, (
void*)items, items_count, height_in_items);
1450 return value_changed;
1454 bool ImGui::Combo(
const char* label,
int* current_item,
const char* items_separated_by_zeros,
int height_in_items)
1456 int items_count = 0;
1457 const char* p = items_separated_by_zeros;
1464 return value_changed;
1487 {
sizeof(int),
"%d",
"%d" },
1488 {
sizeof(
unsigned int),
"%u",
"%u" },
1490 {
sizeof(
ImS64),
"%I64d",
"%I64d" },
1491 {
sizeof(
ImU64),
"%I64u",
"%I64u" },
1493 {
sizeof(
ImS64),
"%lld",
"%lld" },
1494 {
sizeof(
ImU64),
"%llu",
"%llu" },
1496 {
sizeof(float),
"%f",
"%f" },
1497 {
sizeof(double),
"%f",
"%lf" },
1506 if (fmt[0] ==
'%' && fmt[1] ==
'.' && fmt[2] ==
'0' && fmt[3] ==
'f' && fmt[4] == 0)
1510 if (fmt_end > fmt_start && fmt_end[-1] ==
'f')
1512 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1513 if (fmt_start == fmt && fmt_end[0] == 0)
1519 IM_ASSERT(0 &&
"DragInt(): Invalid format string!");
1532 return ImFormatString(buf, buf_size, format, *(
const float*)data_ptr);
1534 return ImFormatString(buf, buf_size, format, *(
const double*)data_ptr);
1546 if (op ==
'+') *(
int*)output = *(
const int*)arg1 + *(
const int*)arg2;
1547 else if (op ==
'-') *(
int*)output = *(
const int*)arg1 - *(
const int*)arg2;
1550 if (op ==
'+') *(
unsigned int*)output = *(
const unsigned int*)arg1 + *(
const ImU32*)arg2;
1551 else if (op ==
'-') *(
unsigned int*)output = *(
const unsigned int*)arg1 - *(
const ImU32*)arg2;
1554 if (op ==
'+') *(
ImS64*)output = *(
const ImS64*)arg1 + *(
const ImS64*)arg2;
1555 else if (op ==
'-') *(
ImS64*)output = *(
const ImS64*)arg1 - *(
const ImS64*)arg2;
1558 if (op ==
'+') *(
ImU64*)output = *(
const ImU64*)arg1 + *(
const ImU64*)arg2;
1559 else if (op ==
'-') *(
ImU64*)output = *(
const ImU64*)arg1 - *(
const ImU64*)arg2;
1562 if (op ==
'+') *(
float*)output = *(
const float*)arg1 + *(
const float*)arg2;
1563 else if (op ==
'-') *(
float*)output = *(
const float*)arg1 - *(
const float*)arg2;
1566 if (op ==
'+') *(
double*)output = *(
const double*)arg1 + *(
const double*)arg2;
1567 else if (op ==
'-') *(
double*)output = *(
const double*)arg1 - *(
const double*)arg2;
1584 if (op ==
'+' || op ==
'*' || op ==
'/')
1601 memcpy(data_backup, data_ptr,
GDataTypeInfo[data_type].Size);
1609 int* v = (
int*)data_ptr;
1612 if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
1615 if (op ==
'+') {
if (sscanf(buf,
"%d", &arg1i)) *v = (
int)(arg0i + arg1i); }
1616 else if (op ==
'*') {
if (sscanf(buf,
"%f", &arg1f)) *v = (
int)(arg0i * arg1f); }
1617 else if (op ==
'/') {
if (sscanf(buf,
"%f", &arg1f) && arg1f != 0.0f) *v = (
int)(arg0i / arg1f); }
1618 else {
if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; }
1624 sscanf(buf, format, data_ptr);
1630 float* v = (
float*)data_ptr;
1631 float arg0f = *v, arg1f = 0.0f;
1632 if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
1634 if (sscanf(buf, format, &arg1f) < 1)
1636 if (op ==
'+') { *v = arg0f + arg1f; }
1637 else if (op ==
'*') { *v = arg0f * arg1f; }
1638 else if (op ==
'/') {
if (arg1f != 0.0
f) *v = arg0f / arg1f; }
1639 else { *v = arg1f; }
1644 double* v = (
double*)data_ptr;
1645 double arg0f = *v, arg1f = 0.0;
1646 if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
1648 if (sscanf(buf, format, &arg1f) < 1)
1650 if (op ==
'+') { *v = arg0f + arg1f; }
1651 else if (op ==
'*') { *v = arg0f * arg1f; }
1652 else if (op ==
'/') {
if (arg1f != 0.0
f) *v = arg0f / arg1f; }
1653 else { *v = arg1f; }
1655 return memcmp(data_backup, data_ptr,
GDataTypeInfo[data_type].Size) != 0;
1660 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 };
1661 if (decimal_precision < 0)
1663 return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] :
ImPow(10.0
f, (
float)-decimal_precision);
1666 template<
typename TYPE>
1667 static const char*
ImAtoi(
const char* src, TYPE* output)
1670 if (*src ==
'-') { negative = 1; src++; }
1671 if (*src ==
'+') { src++; }
1673 while (*src >=
'0' && *src <=
'9')
1674 v = (v * 10) + (*src++ -
'0');
1675 *output = negative ? -v : v;
1679 template<
typename TYPE,
typename SIGNEDTYPE>
1683 if (fmt_start[0] !=
'%' || fmt_start[1] ==
'%')
1687 const char* p = v_str;
1693 ImAtoi(p, (SIGNEDTYPE*)&v);
1717 template<
typename TYPE,
typename SIGNEDTYPE,
typename FLOATTYPE>
1723 const bool has_min_max = (v_min != v_max);
1726 if (v_speed == 0.0f && has_min_max && (v_max - v_min < FLT_MAX))
1730 float adjust_delta = 0.0f;
1735 adjust_delta *= 1.0f / 100.0f;
1737 adjust_delta *= 10.0f;
1745 adjust_delta *= v_speed;
1749 adjust_delta = -adjust_delta;
1754 bool is_already_past_limits_and_pushing_outward = has_min_max && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f));
1755 if (is_just_activated || is_already_past_limits_and_pushing_outward)
1760 else if (adjust_delta != 0.0f)
1770 FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f;
1772 const bool is_power = (power != 1.0f && is_decimal && has_min_max && (v_max - v_min < FLT_MAX));
1776 FLOATTYPE v_old_norm_curved =
ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power);
1777 FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.
DragCurrentAccum / (v_max - v_min));
1778 v_cur = v_min + (TYPE)
ImPow(
ImSaturate((
float)v_new_norm_curved), power) * (v_max - v_min);
1779 v_old_ref_for_accum_remainder = v_old_norm_curved;
1787 v_cur = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_cur);
1793 FLOATTYPE v_cur_norm_curved =
ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power);
1794 g.
DragCurrentAccum -= (float)(v_cur_norm_curved - v_old_ref_for_accum_remainder);
1802 if (v_cur == (TYPE)-0)
1806 if (*v != v_cur && has_min_max)
1808 if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_decimal))
1810 if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_decimal))
1840 case ImGuiDataType_Float:
return DragBehaviorT<float, float, float >(data_type, (
float*)v, v_speed, v_min ? *(
const float* )v_min : -FLT_MAX, v_max ? *(
const float* )v_max : FLT_MAX, format, power, flags);
1841 case ImGuiDataType_Double:
return DragBehaviorT<double,double,double>(data_type, (
double*)v, v_speed, v_min ? *(
const double*)v_min : -DBL_MAX, v_max ? *(
const double*)v_max : DBL_MAX, format, power, flags);
1868 if (!
ItemAdd(total_bb,
id, &frame_bb))
1884 bool start_text_input =
false;
1894 start_text_input =
true;
1920 if (label_size.
x > 0.0f)
1923 return value_changed;
1926 bool ImGui::DragScalarN(
const char* label,
ImGuiDataType data_type,
void* v,
int components,
float v_speed,
const void* v_min,
const void* v_max,
const char* format,
float power)
1933 bool value_changed =
false;
1938 for (
int i = 0; i < components; i++)
1941 value_changed |=
DragScalar(
"##v", data_type, v, v_speed, v_min, v_max, format, power);
1945 v = (
void*)((
char*)v + type_size);
1951 return value_changed;
1954 bool ImGui::DragFloat(
const char* label,
float* v,
float v_speed,
float v_min,
float v_max,
const char* format,
float power)
1959 bool ImGui::DragFloat2(
const char* label,
float v[2],
float v_speed,
float v_min,
float v_max,
const char* format,
float power)
1964 bool ImGui::DragFloat3(
const char* label,
float v[3],
float v_speed,
float v_min,
float v_max,
const char* format,
float power)
1969 bool ImGui::DragFloat4(
const char* label,
float v[4],
float v_speed,
float v_min,
float v_max,
const char* format,
float power)
1974 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)
1985 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);
1988 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);
1995 return value_changed;
1999 bool ImGui::DragInt(
const char* label,
int* v,
float v_speed,
int v_min,
int v_max,
const char* format)
2004 bool ImGui::DragInt2(
const char* label,
int v[2],
float v_speed,
int v_min,
int v_max,
const char* format)
2009 bool ImGui::DragInt3(
const char* label,
int v[3],
float v_speed,
int v_min,
int v_max,
const char* format)
2014 bool ImGui::DragInt4(
const char* label,
int v[4],
float v_speed,
int v_min,
int v_max,
const char* format)
2019 bool ImGui::DragIntRange2(
const char* label,
int* v_current_min,
int* v_current_max,
float v_speed,
int v_min,
int v_max,
const char* format,
const char* format_max)
2030 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);
2033 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);
2041 return value_changed;
2065 template<
typename TYPE,
typename FLOATTYPE>
2072 const TYPE v_clamped = (v_min < v_max) ?
ImClamp(v, v_min, v_max) :
ImClamp(v, v_max, v_min);
2075 if (v_clamped < 0.0f)
2077 const float f = 1.0f - (float)((v_clamped - v_min) / (
ImMin((TYPE)0, v_max) - v_min));
2078 return (1.0f -
ImPow(f, 1.0f/power)) * linear_zero_pos;
2082 const float f = (float)((v_clamped -
ImMax((TYPE)0, v_min)) / (v_max -
ImMax((TYPE)0, v_min)));
2083 return linear_zero_pos +
ImPow(f, 1.0f/power) * (1.0f - linear_zero_pos);
2088 return (
float)((FLOATTYPE)(v_clamped - v_min) / (FLOATTYPE)(v_max - v_min));
2092 template<
typename TYPE,
typename SIGNEDTYPE,
typename FLOATTYPE>
2100 const bool is_power = (power != 1.0f) && is_decimal;
2102 const float grab_padding = 2.0f;
2103 const float slider_sz = (bb.
Max[axis] - bb.
Min[axis]) - grab_padding * 2.0f;
2105 SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
2106 if (!is_decimal && v_range >= 0)
2108 grab_sz =
ImMin(grab_sz, slider_sz);
2109 const float slider_usable_sz = slider_sz - grab_sz;
2110 const float slider_usable_pos_min = bb.
Min[axis] + grab_padding + grab_sz*0.5f;
2111 const float slider_usable_pos_max = bb.
Max[axis] - grab_padding - grab_sz*0.5f;
2114 float linear_zero_pos;
2115 if (is_power && v_min * v_max < 0.0f)
2118 const FLOATTYPE linear_dist_min_to_0 =
ImPow(v_min >= 0 ? (FLOATTYPE)v_min : -(FLOATTYPE)v_min, (FLOATTYPE)1.0f/power);
2119 const FLOATTYPE linear_dist_max_to_0 =
ImPow(v_max >= 0 ? (FLOATTYPE)v_max : -(FLOATTYPE)v_max, (FLOATTYPE)1.0f/power);
2120 linear_zero_pos = (float)(linear_dist_min_to_0 / (linear_dist_min_to_0 + linear_dist_max_to_0));
2125 linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f;
2129 bool value_changed =
false;
2132 bool set_new_value =
false;
2133 float clicked_t = 0.0f;
2142 const float mouse_abs_pos = g.
IO.
MousePos[axis];
2143 clicked_t = (slider_usable_sz > 0.0f) ?
ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f;
2145 clicked_t = 1.0f - clicked_t;
2146 set_new_value =
true;
2157 else if (delta != 0.0f)
2159 clicked_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
2161 if ((decimal_precision > 0) || is_power)
2170 delta = ((delta < 0.0f) ? -1.0f : +1.0f) / (float)v_range;
2176 set_new_value =
true;
2177 if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f))
2178 set_new_value =
false;
2190 if (clicked_t < linear_zero_pos)
2193 float a = 1.0f - (clicked_t / linear_zero_pos);
2194 a =
ImPow(a, power);
2201 if (
ImFabs(linear_zero_pos - 1.0f) > 1.e-6f)
2202 a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos);
2205 a =
ImPow(a, power);
2214 v_new =
ImLerp(v_min, v_max, clicked_t);
2220 FLOATTYPE v_new_off_f = (v_max - v_min) * clicked_t;
2221 TYPE v_new_off_floor = (TYPE)(v_new_off_f);
2222 TYPE v_new_off_round = (TYPE)(v_new_off_f + (FLOATTYPE)0.5);
2223 if (!is_decimal && v_new_off_floor < v_new_off_round)
2224 v_new = v_min + v_new_off_round;
2226 v_new = v_min + v_new_off_floor;
2231 v_new = RoundScalarWithFormatT<TYPE,SIGNEDTYPE>(format, data_type, v_new);
2237 value_changed =
true;
2243 float grab_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
2245 grab_t = 1.0f - grab_t;
2246 const float grab_pos =
ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
2248 *out_grab_bb =
ImRect(grab_pos - grab_sz*0.5f, bb.
Min.
y + grab_padding, grab_pos + grab_sz*0.5f, bb.
Max.
y - grab_padding);
2250 *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);
2252 return value_changed;
2264 return SliderBehaviorT<ImS32, ImS32, float >(bb,
id, data_type, (
ImS32*)v, *(
const ImS32*)v_min, *(
const ImS32*)v_max, format, power, flags, out_grab_bb);
2267 return SliderBehaviorT<ImU32, ImS32, float >(bb,
id, data_type, (
ImU32*)v, *(
const ImU32*)v_min, *(
const ImU32*)v_max, format, power, flags, out_grab_bb);
2270 return SliderBehaviorT<ImS64, ImS64, double>(bb,
id, data_type, (
ImS64*)v, *(
const ImS64*)v_min, *(
const ImS64*)v_max, format, power, flags, out_grab_bb);
2273 return SliderBehaviorT<ImU64, ImS64, double>(bb,
id, data_type, (
ImU64*)v, *(
const ImU64*)v_min, *(
const ImU64*)v_max, format, power, flags, out_grab_bb);
2275 IM_ASSERT(*(
const float*)v_min >= -FLT_MAX/2.0
f && *(
const float*)v_max <= FLT_MAX/2.0
f);
2276 return SliderBehaviorT<float, float, float >(bb,
id, data_type, (
float*)v, *(
const float*)v_min, *(
const float*)v_max, format, power, flags, out_grab_bb);
2278 IM_ASSERT(*(
const double*)v_min >= -DBL_MAX/2.0
f && *(
const double*)v_max <= DBL_MAX/2.0
f);
2279 return SliderBehaviorT<double,double,double>(bb,
id, data_type, (
double*)v, *(
const double*)v_min, *(
const double*)v_max, format, power, flags, out_grab_bb);
2302 if (!
ItemAdd(total_bb,
id, &frame_bb))
2317 bool start_text_input =
false;
2328 start_text_input =
true;
2359 if (label_size.
x > 0.0f)
2362 return value_changed;
2373 bool value_changed =
false;
2378 for (
int i = 0; i < components; i++)
2381 value_changed |=
SliderScalar(
"##v", data_type, v, v_min, v_max, format, power);
2385 v = (
void*)((
char*)v + type_size);
2391 return value_changed;
2394 bool ImGui::SliderFloat(
const char* label,
float* v,
float v_min,
float v_max,
const char* format,
float power)
2399 bool ImGui::SliderFloat2(
const char* label,
float v[2],
float v_min,
float v_max,
const char* format,
float power)
2404 bool ImGui::SliderFloat3(
const char* label,
float v[3],
float v_min,
float v_max,
const char* format,
float power)
2409 bool ImGui::SliderFloat4(
const char* label,
float v[4],
float v_min,
float v_max,
const char* format,
float power)
2414 bool ImGui::SliderAngle(
const char* label,
float* v_rad,
float v_degrees_min,
float v_degrees_max,
const char* format)
2417 format =
"%.0f deg";
2418 float v_deg = (*v_rad) * 360.0f / (2*
IM_PI);
2419 bool value_changed =
SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, 1.0
f);
2420 *v_rad = v_deg * (2*
IM_PI) / 360.0
f;
2421 return value_changed;
2498 if (label_size.
x > 0.0f)
2501 return value_changed;
2538 while (
char c = fmt[0])
2540 if (c ==
'%' && fmt[1] !=
'%')
2554 const unsigned int ignored_uppercase_mask = (1 << (
'I'-
'A')) | (1 << (
'L'-
'A'));
2555 const unsigned int ignored_lowercase_mask = (1 << (
'h'-
'a')) | (1 << (
'j'-
'a')) | (1 << (
'l'-
'a')) | (1 << (
't'-
'a')) | (1 << (
'w'-
'a')) | (1 << (
'z'-
'a'));
2556 for (
char c; (c = *fmt) != 0; fmt++)
2558 if (c >=
'A' && c <=
'Z' && ((1 << (c -
'A')) & ignored_uppercase_mask) == 0)
2560 if (c >=
'a' && c <=
'z' && ((1 << (c -
'a')) & ignored_lowercase_mask) == 0)
2574 if (fmt_start[0] !=
'%')
2577 if (fmt_end[0] == 0)
2579 ImStrncpy(buf, fmt_start,
ImMin((
int)(fmt_end + 1 - fmt_start), buf_size));
2589 return default_precision;
2591 while (*fmt >=
'0' && *fmt <=
'9')
2593 int precision = INT_MAX;
2596 fmt = ImAtoi<int>(fmt + 1, &precision);
2597 if (precision < 0 || precision > 99)
2598 precision = default_precision;
2600 if (*fmt ==
'e' || *fmt ==
'E')
2602 if ((*fmt ==
'g' || *fmt ==
'G') && precision == INT_MAX)
2604 return (precision == INT_MAX) ? default_precision : precision;
2654 bool value_changed =
false;
2675 if (
ButtonEx(
"-",
ImVec2(button_size, button_size), button_flags))
2678 value_changed =
true;
2681 if (
ButtonEx(
"+",
ImVec2(button_size, button_size), button_flags))
2684 value_changed =
true;
2698 return value_changed;
2708 bool value_changed =
false;
2713 for (
int i = 0; i < components; i++)
2716 value_changed |=
InputScalar(
"##v", data_type, v,
step, step_fast, format, flags);
2720 v = (
void*)((
char*)v + type_size);
2726 return value_changed;
2751 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
2754 char format[16] =
"%f";
2755 if (decimal_precision >= 0)
2762 char format[16] =
"%f";
2763 if (decimal_precision >= 0)
2770 char format[16] =
"%f";
2771 if (decimal_precision >= 0)
2778 char format[16] =
"%f";
2779 if (decimal_precision >= 0)
2783 #endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
2824 return InputTextEx(label, buf, (
int)buf_size,
ImVec2(0,0), flags, callback, user_data);
2835 const char*
s = text_begin;
2836 while (
char c = *
s++)
2840 if (
s[0] !=
'\n' &&
s[0] !=
'\r')
2850 const float scale = line_height / font->
FontSize;
2853 float line_width = 0.0f;
2856 while (
s < text_end)
2858 unsigned int c = (
unsigned int)(*
s++);
2861 text_size.
x =
ImMax(text_size.
x, line_width);
2862 text_size.
y += line_height;
2864 if (stop_on_new_line)
2872 line_width += char_width;
2875 if (text_size.
x < line_width)
2876 text_size.
x = line_width;
2879 *out_offset =
ImVec2(line_width, text_size.
y + line_height);
2881 if (line_width > 0 || text_size.
y == 0.0f)
2882 text_size.
y += line_height;
2901 const ImWchar* text = obj->TextW.Data;
2909 r->
num_chars = (int)(text_remaining - (text + line_start_idx));
2912 static bool is_separator(
unsigned int c) {
return ImCharIsBlankW(c) || c==
',' || c==
';' || c==
'(' || c==
')' || c==
'{' || c==
'}' || c==
'[' || c==
']' || c==
'|'; }
2915 #ifdef __APPLE__ // FIXME: Move setting to IO structure
2921 #define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
2922 #define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
2926 ImWchar* dst = obj->TextW.Data + pos;
2933 const ImWchar* src = obj->TextW.Data + pos + n;
2942 const int text_len = obj->CurLenW;
2946 if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA))
2950 if (new_text_len + text_len + 1 > obj->TextW.Size)
2955 obj->TextW.resize(text_len +
ImClamp(new_text_len * 4, 32,
ImMax(256, new_text_len)) + 1);
2958 ImWchar* text = obj->TextW.Data;
2959 if (pos != text_len)
2960 memmove(text + pos + new_text_len, text + pos, (
size_t)(text_len - pos) *
sizeof(
ImWchar));
2961 memcpy(text + pos, new_text, (
size_t)new_text_len *
sizeof(
ImWchar));
2963 obj->CurLenW += new_text_len;
2964 obj->CurLenA += new_text_len_utf8;
2965 obj->TextW[obj->CurLenW] =
'\0';
2971 #define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left
2972 #define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right
2973 #define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up
2974 #define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down
2975 #define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line
2976 #define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line
2977 #define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text
2978 #define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text
2979 #define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor
2980 #define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor
2981 #define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo
2982 #define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo
2983 #define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word
2984 #define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word
2985 #define STB_TEXTEDIT_K_SHIFT 0x20000
2987 #define STB_TEXTEDIT_IMPLEMENTATION
2994 stb_textedit_key(
this, &
StbState, key);
3001 memset(
this, 0,
sizeof(*
this));
3010 char* dst =
Buf + pos;
3011 const char* src =
Buf + pos + bytes_count;
3012 while (
char c = *src++)
3028 const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
3047 memcpy(
Buf + pos, new_text, (
size_t)new_text_len *
sizeof(
char));
3060 unsigned int c = *p_char;
3062 if (c < 128 && c !=
' ' && !isprint((
int)(c & 0xFF)))
3071 if (c >= 0xE000 && c <= 0xF8FF)
3077 if (!(c >=
'0' && c <=
'9') && (c !=
'.') && (c !=
'-') && (c !=
'+') && (c !=
'*') && (c !=
'/'))
3081 if (!(c >=
'0' && c <=
'9') && (c !=
'.') && (c !=
'-') && (c !=
'+') && (c !=
'*') && (c !=
'/') && (c !=
'e') && (c !=
'E'))
3085 if (!(c >=
'0' && c <=
'9') && !(c >=
'a' && c <=
'f') && !(c >=
'A' && c <=
'F'))
3089 if (c >=
'a' && c <=
'z')
3090 *p_char = (c += (
unsigned int)(
'A'-
'a'));
3103 callback_data.
Flags = flags;
3104 callback_data.
UserData = user_data;
3105 if (callback(&callback_data) != 0)
3154 ItemAdd(total_bb,
id, &frame_bb);
3168 if (!
ItemAdd(total_bb,
id, &frame_bb))
3197 const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
3199 const bool user_clicked = hovered && io.
MouseClicked[0];
3203 bool clear_active_id =
false;
3206 if (focus_requested || user_clicked || user_scrolled || user_nav_input_start)
3213 const int prev_len_w = edit_state.
CurLenW;
3214 const int init_buf_len = (int)strlen(buf);
3218 const char* buf_end =
NULL;
3220 edit_state.
CurLenA = (int)(buf_end - buf);
3225 const bool recycle_state = (edit_state.
ID ==
id) && (prev_len_w == edit_state.
CurLenW);
3236 stb_textedit_initialize_state(&edit_state.
StbState, !is_multiline);
3237 if (!is_multiline && focus_requested_by_code)
3241 edit_state.
StbState.insert_mode =
true;
3242 if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.
KeyCtrl)))
3254 clear_active_id =
true;
3257 bool value_changed =
false;
3258 bool enter_pressed =
false;
3259 int backup_current_text_length = 0;
3267 const char* buf_end =
NULL;
3269 edit_state.
CurLenA = (int)(buf_end - buf);
3273 backup_current_text_length = edit_state.
CurLenA;
3304 stb_textedit_click(&edit_state, &edit_state.
StbState, mouse_x, mouse_y);
3310 stb_textedit_drag(&edit_state, &edit_state.
StbState, mouse_x, mouse_y);
3322 if (!ignore_inputs && is_editable && !user_nav_input_start)
3336 bool cancel_edit =
false;
3344 const bool is_wordmove_key_down = is_osx ? io.
KeyAlt : io.
KeyCtrl;
3374 if (!is_multiline || (ctrl_enter_for_new_line && !io.
KeyCtrl) || (!ctrl_enter_for_new_line && io.
KeyCtrl))
3376 enter_pressed = clear_active_id =
true;
3378 else if (is_editable)
3380 unsigned int c =
'\n';
3387 unsigned int c =
'\t';
3393 clear_active_id = cancel_edit =
true;
3395 else if (is_undo || is_redo)
3405 else if (is_cut || is_copy)
3421 stb_textedit_cut(&edit_state, &edit_state.
StbState);
3429 const int clipboard_len = (int)strlen(clipboard);
3431 int clipboard_filtered_len = 0;
3432 for (
const char*
s = clipboard; *
s; )
3440 clipboard_filtered[clipboard_filtered_len++] = (
ImWchar)c;
3442 clipboard_filtered[clipboard_filtered_len] = 0;
3443 if (clipboard_filtered_len > 0)
3445 stb_textedit_paste(&edit_state, &edit_state.
StbState, clipboard_filtered, clipboard_filtered_len);
3455 const char* apply_new_text =
NULL;
3456 int apply_new_text_length = 0;
3470 if (apply_edit_back_to_user_buffer)
3513 callback_data.
Flags = flags;
3514 callback_data.
UserData = callback_user_data;
3516 callback_data.
EventKey = event_key;
3529 callback(&callback_data);
3541 if (callback_data.
BufTextLen > backup_current_text_length && is_resizable)
3554 apply_new_text_length = edit_state.
CurLenA;
3562 if (backup_current_text_length != apply_new_text_length && is_resizable)
3566 callback_data.
Flags = flags;
3567 callback_data.
Buf = buf;
3568 callback_data.
BufTextLen = apply_new_text_length;
3569 callback_data.
BufSize =
ImMax(buf_size, apply_new_text_length + 1);
3570 callback_data.
UserData = callback_user_data;
3571 callback(&callback_data);
3572 buf = callback_data.
Buf;
3573 buf_size = callback_data.
BufSize;
3574 apply_new_text_length =
ImMin(callback_data.
BufTextLen, buf_size - 1);
3575 IM_ASSERT(apply_new_text_length <= buf_size);
3580 value_changed =
true;
3590 if (clear_active_id && g.
ActiveId ==
id)
3600 const int buf_display_max_length = 2 * 1024 * 1024;
3611 const bool is_currently_scrolling = (edit_state.
ID ==
id && is_multiline && g.
ActiveId == draw_window->
GetIDNoKeepAlive(
"#SCROLLY"));
3612 if (g.
ActiveId ==
id || is_currently_scrolling)
3623 ImVec2 cursor_offset, select_start_offset;
3627 const ImWchar* searches_input_ptr[2];
3628 searches_input_ptr[0] = text_begin + edit_state.
StbState.cursor;
3629 searches_input_ptr[1] =
NULL;
3630 int searches_remaining = 1;
3631 int searches_result_line_number[2] = { -1, -999 };
3634 searches_input_ptr[1] = text_begin +
ImMin(edit_state.
StbState.select_start, edit_state.
StbState.select_end);
3635 searches_result_line_number[1] = -1;
3636 searches_remaining++;
3641 searches_remaining += is_multiline ? 1 : 0;
3644 for (
const ImWchar*
s = text_begin; *
s != 0;
s++)
3648 if (searches_result_line_number[0] == -1 &&
s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count;
if (--searches_remaining <= 0)
break; }
3649 if (searches_result_line_number[1] == -1 &&
s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count;
if (--searches_remaining <= 0)
break; }
3652 if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count;
3653 if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count;
3657 cursor_offset.
y = searches_result_line_number[0] * g.
FontSize;
3658 if (searches_result_line_number[1] >= 0)
3661 select_start_offset.
y = searches_result_line_number[1] * g.
FontSize;
3675 const float scroll_increment_x = size.
x * 0.25f;
3676 if (cursor_offset.
x < edit_state.
ScrollX)
3677 edit_state.
ScrollX = (float)(
int)
ImMax(0.0
f, cursor_offset.
x - scroll_increment_x);
3678 else if (cursor_offset.
x - size.
x >= edit_state.
ScrollX)
3679 edit_state.
ScrollX = (float)(
int)(cursor_offset.
x - size.
x + scroll_increment_x);
3689 float scroll_y = draw_window->
Scroll.
y;
3690 if (cursor_offset.
y - g.
FontSize < scroll_y)
3692 else if (cursor_offset.
y - size.
y >= scroll_y)
3693 scroll_y = cursor_offset.
y - size.
y;
3695 draw_window->
Scroll.
y = scroll_y;
3708 float bg_offy_up = is_multiline ? 0.0f : -1.0f;
3709 float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
3711 ImVec2 rect_pos = render_pos + select_start_offset - render_scroll;
3712 for (
const ImWchar* p = text_selected_begin; p < text_selected_end; )
3716 if (rect_pos.
y < clip_rect.
y)
3720 while (p < text_selected_end)
3733 rect_pos.
x = render_pos.
x - render_scroll.x;
3738 const int buf_display_len = edit_state.
CurLenA;
3739 if (is_multiline || buf_display_len < buf_display_max_length)
3744 ImVec2 cursor_screen_pos = render_pos + cursor_offset - render_scroll;
3745 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);
3746 if (cursor_is_visible && cursor_screen_rect.
Overlaps(clip_rect))
3756 const char* buf_end =
NULL;
3760 buf_end = buf_display + strlen(buf_display);
3761 if (is_multiline || (buf_end - buf_display) < buf_display_max_length)
3779 if (label_size.
x > 0)
3786 return enter_pressed;
3788 return value_changed;
3850 const int components = alpha ? 4 : 3;
3853 float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f };
3858 bool value_changed =
false;
3859 bool value_changed_as_float =
false;
3864 const float w_item_one =
ImMax(1.0
f, (
float)(
int)((w_items_all - (style.
ItemInnerSpacing.
x) * (components-1)) / (
float)components));
3865 const float w_item_last =
ImMax(1.0
f, (
float)(
int)(w_items_all - (w_item_one + style.
ItemInnerSpacing.
x) * (components-1)));
3868 const char* ids[4] = {
"##X",
"##Y",
"##Z",
"##W" };
3869 const char* fmt_table_int[3][4] =
3871 {
"%3d",
"%3d",
"%3d",
"%3d" },
3872 {
"R:%3d",
"G:%3d",
"B:%3d",
"A:%3d" },
3873 {
"H:%3d",
"S:%3d",
"V:%3d",
"A:%3d" }
3875 const char* fmt_table_float[3][4] =
3877 {
"%0.3f",
"%0.3f",
"%0.3f",
"%0.3f" },
3878 {
"R:%0.3f",
"G:%0.3f",
"B:%0.3f",
"A:%0.3f" },
3879 {
"H:%0.3f",
"S:%0.3f",
"V:%0.3f",
"A:%0.3f" }
3884 for (
int n = 0; n < components; n++)
3888 if (n + 1 == components)
3891 value_changed = value_changed_as_float = 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]);
3893 value_changed |=
DragInt(ids[n], &i[n], 1.0
f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);
3905 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));
3907 ImFormatString(buf,
IM_ARRAYSIZE(buf),
"#%02X%02X%02X",
ImClamp(i[0],0,255),
ImClamp(i[1],0,255),
ImClamp(i[2],0,255));
3911 value_changed =
true;
3915 i[0] = i[1] = i[2] = i[3] = 0;
3917 sscanf(p,
"%02X%02X%02X%02X", (
unsigned int*)&i[0], (
unsigned int*)&i[1], (
unsigned int*)&i[2], (
unsigned int*)&i[3]);
3919 sscanf(p,
"%02X%02X%02X", (
unsigned int*)&i[0], (
unsigned int*)&i[1], (
unsigned int*)&i[2]);
3932 const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0
f);
3949 if (label != label_display_end)
3970 if (picker_active_window ==
NULL)
3972 if (!value_changed_as_float)
3973 for (
int n = 0; n < 4; n++)
3974 f[n] = i[n] / 255.0
f;
3996 memcpy((
float*)col, payload->Data,
sizeof(
float) * 3);
3997 value_changed =
true;
4001 memcpy((
float*)col, payload->Data,
sizeof(
float) * components);
4002 value_changed =
true;
4014 return value_changed;
4019 float col4[4] = { col[0], col[1], col[2], 1.0f };
4022 col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2];
4048 for (
float y = p_min.
y + grid_off.
y; y < p_max.
y; y += grid_step, yi++)
4050 float y1 =
ImClamp(y, p_min.
y, p_max.
y), y2 =
ImMin(y + grid_step, p_max.
y);
4053 for (
float x = p_min.
x + grid_off.
x + (yi & 1) * grid_step; x < p_max.
x; x += grid_step * 2.0f)
4055 float x1 =
ImClamp(x, p_min.
x, p_max.
x), x2 =
ImMin(x + grid_step, p_max.
x);
4058 int rounding_corners_flags_cell = 0;
4061 rounding_corners_flags_cell &= rounding_corners_flags;
4114 float bars_width = square_sz;
4118 float bars_triangles_half_sz = (float)(
int)(bars_width * 0.20f);
4120 float backup_initial_col[4];
4121 memcpy(backup_initial_col, col, components *
sizeof(
float));
4123 float wheel_thickness = sv_picker_size * 0.08f;
4124 float wheel_r_outer = sv_picker_size * 0.50f;
4125 float wheel_r_inner = wheel_r_outer - wheel_thickness;
4126 ImVec2 wheel_center(picker_pos.
x + (sv_picker_size + bars_width)*0.5f, picker_pos.
y + sv_picker_size*0.5f);
4129 float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027
f);
4131 ImVec2 triangle_pb =
ImVec2(triangle_r * -0.5
f, triangle_r * -0.866025
f);
4132 ImVec2 triangle_pc =
ImVec2(triangle_r * -0.5
f, triangle_r * +0.866025
f);
4137 bool value_changed =
false, value_changed_h =
false, value_changed_sv =
false;
4149 if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1))
4155 value_changed = value_changed_h =
true;
4162 ImVec2 current_off_unrotated =
ImRotate(current_off, cos_hue_angle, sin_hue_angle);
4164 current_off_unrotated =
ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);
4169 value_changed = value_changed_sv =
true;
4183 value_changed = value_changed_sv =
true;
4194 value_changed = value_changed_h =
true;
4206 value_changed =
true;
4220 if (label != label_display_end)
4235 if (ref_col !=
NULL)
4241 memcpy(col, ref_col, components *
sizeof(
float));
4242 value_changed =
true;
4250 if (value_changed_h || value_changed_sv)
4254 bool value_changed_fix_hue_wrap =
false;
4257 PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.
x);
4266 value_changed =
true;
4276 if (value_changed_fix_hue_wrap)
4278 float new_H, new_S, new_V;
4280 if (new_H <= 0 && H > 0)
4282 if (new_V <= 0 && V != new_V)
4284 else if (new_S <= 0)
4293 const ImU32 hue_colors[6+1] = {
IM_COL32(255,0,0,255),
IM_COL32(255,255,0,255),
IM_COL32(0,255,0,255),
IM_COL32(0,255,255,255),
IM_COL32(0,0,255,255),
IM_COL32(255,0,255,255),
IM_COL32(255,0,0,255) };
4299 const float aeps = 1.5f / wheel_r_outer;
4300 const int segment_per_arc =
ImMax(4, (
int)wheel_r_outer / 12);
4301 for (
int n = 0; n < 6; n++)
4303 const float a0 = (n) /6.0
f * 2.0
f *
IM_PI - aeps;
4304 const float a1 = (n+1.0f)/6.0
f * 2.0
f *
IM_PI + aeps;
4306 draw_list->
PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
4311 ImVec2 gradient_p0(wheel_center.
x +
ImCos(a0) * wheel_r_inner, wheel_center.
y +
ImSin(a0) * wheel_r_inner);
4312 ImVec2 gradient_p1(wheel_center.
x +
ImCos(a1) * wheel_r_inner, wheel_center.
y +
ImSin(a1) * wheel_r_inner);
4319 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);
4320 float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
4321 int hue_cursor_segments =
ImClamp((
int)(hue_cursor_rad / 1.4
f), 9, 32);
4322 draw_list->
AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
4323 draw_list->
AddCircle(hue_cursor_pos, hue_cursor_rad+1,
IM_COL32(128,128,128,255), hue_cursor_segments);
4327 ImVec2 tra = wheel_center +
ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
4328 ImVec2 trb = wheel_center +
ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
4329 ImVec2 trc = wheel_center +
ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
4332 draw_list->
PrimVtx(tra, uv_white, hue_color32);
4333 draw_list->
PrimVtx(trb, uv_white, hue_color32);
4347 sv_cursor_pos.
x =
ImClamp((
float)(
int)(picker_pos.
x +
ImSaturate(S) * sv_picker_size + 0.5
f), picker_pos.
x + 2, picker_pos.
x + sv_picker_size - 2);
4348 sv_cursor_pos.
y =
ImClamp((
float)(
int)(picker_pos.
y +
ImSaturate(1 - V) * sv_picker_size + 0.5
f), picker_pos.
y + 2, picker_pos.
y + sv_picker_size - 2);
4351 for (
int i = 0; i < 6; ++i)
4352 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)), hue_colors[i], hue_colors[i], hue_colors[i + 1], hue_colors[i + 1]);
4353 float bar0_line_y = (float)(
int)(picker_pos.
y + H * sv_picker_size + 0.5f);
4359 float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
4360 draw_list->
AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_alpha, 12);
4361 draw_list->
AddCircle(sv_cursor_pos, sv_cursor_rad+1,
IM_COL32(128,128,128,255), 12);
4368 ImRect bar1_bb(bar1_pos_x, picker_pos.
y, bar1_pos_x + bars_width, picker_pos.
y + sv_picker_size);
4371 float bar1_line_y = (float)(
int)(picker_pos.
y + (1.0f - alpha) * sv_picker_size + 0.5
f);
4378 if (value_changed && memcmp(backup_initial_col, col, components *
sizeof(
float)) == 0)
4379 value_changed =
false;
4385 return value_changed;
4401 size.
x = default_size;
4403 size.
y = default_size;
4415 ImVec4 col_without_alpha(col.
x, col.
y, col.
z, 1.0f);
4416 float grid_step =
ImMin(size.
x, size.
y) / 2.99f;
4423 float mid_x = (float)(
int)((bb_inner.
Min.
x + bb_inner.
Max.
x) * 0.5
f + 0.5
f);
4431 if (col_source.
w < 1.0f)
4490 if (text_end > text)
4500 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]);
4502 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]);
4510 if ((!allow_opt_inputs && !allow_opt_datatype) || !
BeginPopup(
"context"))
4514 if (allow_opt_inputs)
4520 if (allow_opt_datatype)
4527 if (allow_opt_inputs || allow_opt_datatype)
4558 if ((!allow_opt_picker && !allow_opt_alpha_bar) || !
BeginPopup(
"context"))
4561 if (allow_opt_picker)
4565 for (
int picker_type = 0; picker_type < 2; picker_type++)
4574 if (
Selectable(
"##selectable",
false, 0, picker_size))
4579 ColorPicker4(
"##dummypicker", &dummy_ref_col.
x, picker_flags);
4584 if (allow_opt_alpha_bar)
4611 va_start(
args, fmt);
4620 va_start(
args, fmt);
4656 va_start(
args, fmt);
4665 va_start(
args, fmt);
4709 storage->
SetInt(
id, is_open);
4714 const int stored_value = storage->
GetInt(
id, -1);
4715 if (stored_value == -1)
4718 storage->
SetInt(
id, is_open);
4722 is_open = stored_value != 0;
4766 const float text_offset_x = (g.
FontSize + (display_frame ? padding.
x*3 : padding.
x*2));
4767 const float text_width = g.
FontSize + (label_size.
x > 0.0f ? label_size.
x + padding.
x*2 : 0.0f);
4782 bool item_add =
ItemAdd(interact_bb,
id);
4805 bool hovered, held, pressed =
ButtonBehavior(interact_bb,
id, &hovered, &held, button_flags);
4808 bool toggled =
false;
4842 const ImVec2 text_pos = frame_bb.
Min +
ImVec2(text_offset_x, text_base_offset_y);
4852 const char log_prefix[] =
"\n##";
4853 const char log_suffix[] =
"##";
4878 RenderText(text_pos, label, label_end,
false);
4892 PushID(str_id ? str_id :
"#TreePush");
4900 PushID(ptr_id ? ptr_id : (
const void*)
"#TreePush");
4969 if (p_open && !*p_open)
4979 float button_radius = g.
FontSize * 0.5f;
4981 if (
CloseButton(window->
GetID((
void*)(intptr_t)(
id+1)), button_center, button_radius))
5011 ImVec2 size(size_arg.
x != 0.0f ? size_arg.
x : label_size.
x, size_arg.
y != 0.0f ? size_arg.
y : label_size.
y);
5014 ImRect bb_inner(pos, pos + size);
5022 ImRect bb(pos, pos + size_draw);
5024 bb.
Max.
x += window_padding.
x;
5027 float spacing_L = (float)(
int)(style.
ItemSpacing.
x * 0.5f);
5028 float spacing_U = (float)(
int)(style.
ItemSpacing.
y * 0.5f);
5031 bb.
Min.
x -= spacing_L;
5032 bb.
Min.
y -= spacing_U;
5033 bb.
Max.
x += spacing_R;
5034 bb.
Max.
y += spacing_D;
5050 bool pressed =
ButtonBehavior(bb,
id, &hovered, &held, button_flags);
5055 if (pressed || hovered)
5065 if (hovered || selected)
5090 if (
Selectable(label, *p_selected, flags, size_arg))
5092 *p_selected = !*p_selected;
5127 if (label_size.
x > 0)
5141 if (height_in_items < 0)
5142 height_in_items =
ImMin(items_count, 7);
5144 float height_in_items_f = (height_in_items < items_count) ? (height_in_items + 0.25
f) : (height_in_items + 0.00f);
5170 bool ImGui::ListBox(
const char* label,
int* current_item,
const char*
const items[],
int items_count,
int height_items)
5172 const bool value_changed =
ListBox(label, current_item,
Items_ArrayGetter, (
void*)items, items_count, height_items);
5173 return value_changed;
5176 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)
5183 bool value_changed =
false;
5185 while (clipper.Step())
5186 for (
int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
5188 const bool item_selected = (i == *current_item);
5189 const char* item_text;
5190 if (!items_getter(data, i, &item_text))
5191 item_text =
"*Unknown item*";
5197 value_changed =
true;
5207 return value_changed;
5218 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 graph_size)
5228 if (graph_size.
x == 0.0f)
5230 if (graph_size.
y == 0.0f)
5237 if (!
ItemAdd(total_bb, 0, &frame_bb))
5242 if (scale_min == FLT_MAX || scale_max == FLT_MAX)
5244 float v_min = FLT_MAX;
5245 float v_max = -FLT_MAX;
5246 for (
int i = 0; i < values_count; i++)
5248 const float v = values_getter(data, i);
5249 v_min =
ImMin(v_min, v);
5250 v_max =
ImMax(v_max, v);
5252 if (scale_min == FLT_MAX)
5254 if (scale_max == FLT_MAX)
5260 if (values_count > 0)
5270 const int v_idx = (int)(
t * item_count);
5271 IM_ASSERT(v_idx >= 0 && v_idx < values_count);
5273 const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
5274 const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);
5276 SetTooltip(
"%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1);
5282 const float t_step = 1.0f / (float)res_w;
5283 const float inv_scale = (scale_min == scale_max) ? 0.0
f : (1.0
f / (scale_max - scale_min));
5285 float v0 = values_getter(data, (0 + values_offset) % values_count);
5288 float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f);
5293 for (
int n = 0; n < res_w; n++)
5295 const float t1 = t0 + t_step;
5296 const int v1_idx = (int)(t0 * item_count + 0.5
f);
5297 IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
5298 const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
5306 window->
DrawList->
AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
5310 if (pos1.
x >= pos0.
x + 2.0f)
5324 if (label_size.
x > 0.0f)
5339 const float v = *(
const float*)(
const void*)((
const unsigned char*)plot_data->
Values + (
size_t)idx * plot_data->
Stride);
5343 void ImGui::PlotLines(
const char* label,
const float* values,
int values_count,
int values_offset,
const char* overlay_text,
float scale_min,
float scale_max,
ImVec2 graph_size,
int stride)
5349 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)
5351 PlotEx(
ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5354 void ImGui::PlotHistogram(
const char* label,
const float* values,
int values_count,
int values_offset,
const char* overlay_text,
float scale_min,
float scale_max,
ImVec2 graph_size,
int stride)
5360 void ImGui::PlotHistogram(
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)
5374 Text(
"%s: %s", prefix, (b ?
"true" :
"false"));
5379 Text(
"%s: %d", prefix, v);
5384 Text(
"%s: %d", prefix, v);
5393 Text(fmt, prefix, v);
5397 Text(
"%s: %.3f", prefix, v);
5419 memset(
Pos, 0,
sizeof(
Pos));
5430 for (
int i = 0; i <
Count; i++)
5446 for (
int i = 0; i < 3; i++)
5573 if (menuset_is_open)
5586 float w = label_size.
x;
5604 if (menuset_is_open)
5607 bool want_open =
false, want_close =
false;
5611 bool moving_within_opened_triangle =
false;
5616 ImRect next_window_rect = next_window->Rect();
5618 ImVec2 tb = (window->
Pos.
x < next_window->Pos.x) ? next_window_rect.
GetTL() : next_window_rect.
GetTR();
5619 ImVec2 tc = (window->
Pos.
x < next_window->Pos.x) ? next_window_rect.
GetBL() : next_window_rect.
GetBR();
5621 ta.
x += (window->
Pos.
x < next_window->Pos.x) ? -0.5
f : +0.5
f;
5622 tb.
y = ta.
y +
ImMax((tb.
y - extra) - ta.
y, -100.0f);
5623 tc.
y = ta.
y +
ImMin((tc.
y + extra) - ta.
y, +100.0f);
5630 want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed);
5634 want_close = menu_is_open;
5635 want_open = !menu_is_open;
5646 if (menu_is_open && pressed && menuset_is_open)
5649 want_open = menu_is_open =
false;
5651 else if (pressed || (hovered && menuset_is_open && !menu_is_open))
5676 menu_is_open |= want_open;
5690 return menu_is_open;
5709 bool ImGui::MenuItem(
const char* label,
const char* shortcut,
bool selected,
bool enabled)
5726 float w = label_size.
x;
5739 if (shortcut_size.
x > 0.0f)
5753 bool ImGui::MenuItem(
const char* label,
const char* shortcut,
bool* p_selected,
bool enabled)
5755 if (
MenuItem(label, shortcut, p_selected ? *p_selected :
false, enabled))
5758 *p_selected = !*p_selected;
5866 tab_bar->
Flags = flags;
5867 tab_bar->
BarRect = tab_bar_bb;
5920 for (
int tab_src_n = 0; tab_src_n < tab_bar->
Tabs.
Size; tab_src_n++)
5929 if (tab_dst_n != tab_src_n)
5930 tab_bar->
Tabs[tab_dst_n] = tab_bar->
Tabs[tab_src_n];
5933 if (tab_bar->
Tabs.
Size != tab_dst_n)
5937 ImGuiID scroll_track_selected_tab_id = 0;
5952 if (tab2_order >= 0 && tab2_order < tab_bar->Tabs.Size)
5959 scroll_track_selected_tab_id = tab2->
ID;
5972 float width_total_contents = 0.0f;
5974 bool found_selected_tab_id =
false;
5975 for (
int tab_n = 0; tab_n < tab_bar->
Tabs.
Size; tab_n++)
5981 most_recently_selected_tab = tab;
5983 found_selected_tab_id =
true;
5991 width_sort_buffer[tab_n].Index = tab_n;
5997 float width_excess = (width_avail < width_total_contents) ? (width_total_contents - width_avail) : 0.0f;
6003 int tab_count_same_width = 1;
6004 while (width_excess > 0.0
f && tab_count_same_width < tab_bar->Tabs.Size)
6006 while (tab_count_same_width < tab_bar->Tabs.Size && width_sort_buffer[0].Width == width_sort_buffer[tab_count_same_width].Width)
6007 tab_count_same_width++;
6008 float width_to_remove_per_tab_max = (tab_count_same_width < tab_bar->
Tabs.
Size) ? (width_sort_buffer[0].Width - width_sort_buffer[tab_count_same_width].Width) : (width_sort_buffer[0].Width - 1.0f);
6009 float width_to_remove_per_tab =
ImMin(width_excess / tab_count_same_width, width_to_remove_per_tab_max);
6010 for (
int tab_n = 0; tab_n < tab_count_same_width; tab_n++)
6011 width_sort_buffer[tab_n].Width -= width_to_remove_per_tab;
6012 width_excess -= width_to_remove_per_tab * tab_count_same_width;
6014 for (
int tab_n = 0; tab_n < tab_bar->
Tabs.
Size; tab_n++)
6015 tab_bar->
Tabs[width_sort_buffer[tab_n].Index].Width = (
float)(int)width_sort_buffer[tab_n].Width;
6020 for (
int tab_n = 0; tab_n < tab_bar->
Tabs.
Size; tab_n++)
6028 float offset_x = 0.0f;
6029 for (
int tab_n = 0; tab_n < tab_bar->
Tabs.
Size; tab_n++)
6034 scroll_track_selected_tab_id = tab->
ID;
6042 if (scrolling_buttons)
6044 scroll_track_selected_tab_id = tab_bar->
SelectedTabId = tab_to_select->ID;
6047 if (found_selected_tab_id ==
false)
6050 scroll_track_selected_tab_id = tab_bar->
SelectedTabId = most_recently_selected_tab->
ID;
6057 if (scroll_track_selected_tab_id)
6079 return window->
GetID(label);
6092 for (
int n = 0; n < tab_bar->
Tabs.
Size; n++)
6093 if (tab_bar->
Tabs[n].ID == tab_id)
6094 return &tab_bar->
Tabs[n];
6128 return ImMax(scrolling, 0.0
f);
6136 float tab_x1 = tab->
Offset + (order > 0 ? -margin : 0.0f);
6137 float tab_x2 = tab->
Offset + tab->
Width + (order + 1 < tab_bar->
Tabs.
Size ? margin : 1.0f);
6158 const float scrolling_buttons_width = arrow_button_size.
x * 2.0f;
6172 arrow_col.
w *= 0.5f;
6193 if (select_dir != 0)
6196 int selected_order = tab_bar->
GetTabOrder(tab_item);
6197 int target_order = selected_order + select_dir;
6198 tab_to_select = &tab_bar->
Tabs[(target_order >= 0 && target_order < tab_bar->
Tabs.
Size) ? target_order : selected_order];
6201 tab_bar->
BarRect.
Max.
x -= scrolling_buttons_width + 1.0f;
6203 return tab_to_select;
6229 bool ret =
TabItemEx(tab_bar, label, p_open, flags);
6267 if (p_open && !*p_open)
6280 bool tab_is_new =
false;
6313 if (tab_contents_visible)
6317 if (!tab_contents_visible && tab_bar->
SelectedTabId == 0 && tab_bar_appearing)
6319 tab_contents_visible =
true;
6321 if (tab_appearing && !(tab_bar_appearing && !tab_is_new))
6326 return tab_contents_visible;
6339 ImRect bb(pos, pos + size);
6352 return tab_contents_visible;
6360 bool pressed =
ButtonBehavior(bb,
id, &hovered, &held, button_flags);
6413 const ImGuiID close_button_id = p_open ? window->
GetID((
void*)(intptr_t)(
id + 1)) : 0;
6431 return tab_contents_visible;
6440 if (is_within_manual_tab_bar)
6454 if (has_close_button)
6469 float y1 = bb.
Min.
y + 1.0f;
6470 float y2 = bb.
Max.
y - 1.0f;
6491 const char* TAB_UNSAVED_MARKER =
"*";
6499 ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
6506 bool close_button_pressed =
false;
6507 bool close_button_visible =
false;
6508 if (close_button_id != 0)
6510 close_button_visible =
true;
6511 if (close_button_visible)
6514 const float close_button_sz = g.
FontSize * 0.5f;
6516 close_button_pressed =
true;
6521 close_button_pressed =
true;
6523 text_pixel_clip_bb.
Max.
x -= close_button_sz * 2.0f;
6529 if (label_size.
x > text_ellipsis_clip_bb.
GetWidth())
6531 const int ellipsis_dot_count = 3;
6532 const float ellipsis_width = (1.0f + 1.0f) * ellipsis_dot_count - 1.0
f;
6533 const char* label_end =
NULL;
6534 float label_size_clipped_x = g.
Font->
CalcTextSizeA(g.
FontSize, text_ellipsis_clip_bb.
GetWidth() - ellipsis_width + 1.0f, 0.0f, label, label_display_end, &label_end).x;
6535 if (label_end == label && label_end < label_display_end)
6547 const float ellipsis_x = text_pixel_clip_bb.
Min.
x + label_size_clipped_x + 1.0f;
6548 if (!close_button_visible && ellipsis_x + ellipsis_width <= bb.
Max.
x)
6556 return close_button_pressed;