imgui_widgets.cpp
Go to the documentation of this file.
1 // dear imgui, v1.67 WIP
2 // (widgets code)
3 
4 /*
5 
6 Index of this file:
7 
8 // [SECTION] Forward Declarations
9 // [SECTION] Widgets: Text, etc.
10 // [SECTION] Widgets: Main (Button, Image, Checkbox, RadioButton, ProgressBar, Bullet, etc.)
11 // [SECTION] Widgets: Low-level Layout helpers (Spacing, Dummy, NewLine, Separator, etc.)
12 // [SECTION] Widgets: ComboBox
13 // [SECTION] Data Type and Data Formatting Helpers
14 // [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc.
15 // [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc.
16 // [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc.
17 // [SECTION] Widgets: InputText, InputTextMultiline
18 // [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc.
19 // [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
20 // [SECTION] Widgets: Selectable
21 // [SECTION] Widgets: ListBox
22 // [SECTION] Widgets: PlotLines, PlotHistogram
23 // [SECTION] Widgets: Value helpers
24 // [SECTION] Widgets: MenuItem, BeginMenu, EndMenu, etc.
25 // [SECTION] Widgets: BeginTabBar, EndTabBar, etc.
26 // [SECTION] Widgets: BeginTabItem, EndTabItem, etc.
27 
28 */
29 
30 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
31 #define _CRT_SECURE_NO_WARNINGS
32 #endif
33 
34 #include "imgui.h"
35 #ifndef IMGUI_DEFINE_MATH_OPERATORS
36 #define IMGUI_DEFINE_MATH_OPERATORS
37 #endif
38 #include "imgui_internal.h"
39 
40 #include <ctype.h> // toupper, isprint
41 #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
42 #include <stddef.h> // intptr_t
43 #else
44 #include <stdint.h> // intptr_t
45 #endif
46 
47 // Visual Studio warnings
48 #ifdef _MSC_VER
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
51 #endif
52 
53 // Clang/GCC warnings with -Weverything
54 #ifdef __clang__
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
59 #if __GNUC__ >= 8
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
61 #endif
62 #endif
63 
64 //-------------------------------------------------------------------------
65 // Data
66 //-------------------------------------------------------------------------
67 
68 // Those MIN/MAX values are not define because we need to point to them
69 static const ImS32 IM_S32_MIN = INT_MIN; // (-2147483647 - 1), (0x80000000);
70 static const ImS32 IM_S32_MAX = INT_MAX; // (2147483647), (0x7FFFFFFF)
71 static const ImU32 IM_U32_MIN = 0;
72 static const ImU32 IM_U32_MAX = UINT_MAX; // (0xFFFFFFFF)
73 #ifdef LLONG_MIN
74 static const ImS64 IM_S64_MIN = LLONG_MIN; // (-9223372036854775807ll - 1ll);
75 static const ImS64 IM_S64_MAX = LLONG_MAX; // (9223372036854775807ll);
76 #else
77 static const ImS64 IM_S64_MIN = -9223372036854775807LL - 1;
78 static const ImS64 IM_S64_MAX = 9223372036854775807LL;
79 #endif
80 static const ImU64 IM_U64_MIN = 0;
81 #ifdef ULLONG_MAX
82 static const ImU64 IM_U64_MAX = ULLONG_MAX; // (0xFFFFFFFFFFFFFFFFull);
83 #else
84 static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1);
85 #endif
86 
87 //-------------------------------------------------------------------------
88 // [SECTION] Forward Declarations
89 //-------------------------------------------------------------------------
90 
91 // Data Type helpers
92 static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format);
93 static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2);
94 static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format);
95 
96 // For InputTextEx()
97 static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data);
98 static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
99 static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
100 
101 //-------------------------------------------------------------------------
102 // [SECTION] Widgets: Text, etc.
103 //-------------------------------------------------------------------------
104 // - TextUnformatted()
105 // - Text()
106 // - TextV()
107 // - TextColored()
108 // - TextColoredV()
109 // - TextDisabled()
110 // - TextDisabledV()
111 // - TextWrapped()
112 // - TextWrappedV()
113 // - LabelText()
114 // - LabelTextV()
115 // - BulletText()
116 // - BulletTextV()
117 //-------------------------------------------------------------------------
118 
119 void ImGui::TextUnformatted(const char* text, const char* text_end)
120 {
121  ImGuiWindow* window = GetCurrentWindow();
122  if (window->SkipItems)
123  return;
124 
125  ImGuiContext& g = *GImGui;
126  IM_ASSERT(text != NULL);
127  const char* text_begin = text;
128  if (text_end == NULL)
129  text_end = text + strlen(text); // FIXME-OPT
130 
131  const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
132  const float wrap_pos_x = window->DC.TextWrapPos;
133  const bool wrap_enabled = wrap_pos_x >= 0.0f;
134  if (text_end - text > 2000 && !wrap_enabled)
135  {
136  // Long text!
137  // Perform manual coarse clipping to optimize for long multi-line text
138  // - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
139  // - We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
140  // - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop.
141  const char* line = text;
142  const float line_height = GetTextLineHeight();
143  const ImRect clip_rect = window->ClipRect;
144  ImVec2 text_size(0,0);
145 
146  if (text_pos.y <= clip_rect.Max.y)
147  {
148  ImVec2 pos = text_pos;
149 
150  // Lines to skip (can't skip when logging text)
151  if (!g.LogEnabled)
152  {
153  int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height);
154  if (lines_skippable > 0)
155  {
156  int lines_skipped = 0;
157  while (line < text_end && lines_skipped < lines_skippable)
158  {
159  const char* line_end = (const char*)memchr(line, '\n', text_end - line);
160  if (!line_end)
161  line_end = text_end;
162  line = line_end + 1;
163  lines_skipped++;
164  }
165  pos.y += lines_skipped * line_height;
166  }
167  }
168 
169  // Lines to render
170  if (line < text_end)
171  {
172  ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
173  while (line < text_end)
174  {
175  if (IsClippedEx(line_rect, 0, false))
176  break;
177 
178  const char* line_end = (const char*)memchr(line, '\n', text_end - line);
179  if (!line_end)
180  line_end = text_end;
181  const ImVec2 line_size = CalcTextSize(line, line_end, false);
182  text_size.x = ImMax(text_size.x, line_size.x);
183  RenderText(pos, line, line_end, false);
184  line = line_end + 1;
185  line_rect.Min.y += line_height;
186  line_rect.Max.y += line_height;
187  pos.y += line_height;
188  }
189 
190  // Count remaining lines
191  int lines_skipped = 0;
192  while (line < text_end)
193  {
194  const char* line_end = (const char*)memchr(line, '\n', text_end - line);
195  if (!line_end)
196  line_end = text_end;
197  line = line_end + 1;
198  lines_skipped++;
199  }
200  pos.y += lines_skipped * line_height;
201  }
202 
203  text_size.y += (pos - text_pos).y;
204  }
205 
206  ImRect bb(text_pos, text_pos + text_size);
207  ItemSize(text_size);
208  ItemAdd(bb, 0);
209  }
210  else
211  {
212  const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
213  const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
214 
215  // Account of baseline offset
216  ImRect bb(text_pos, text_pos + text_size);
217  ItemSize(text_size);
218  if (!ItemAdd(bb, 0))
219  return;
220 
221  // Render (we don't hide text after ## in this end-user function)
222  RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
223  }
224 }
225 
226 void ImGui::Text(const char* fmt, ...)
227 {
228  va_list args;
229  va_start(args, fmt);
230  TextV(fmt, args);
231  va_end(args);
232 }
233 
234 void ImGui::TextV(const char* fmt, va_list args)
235 {
236  ImGuiWindow* window = GetCurrentWindow();
237  if (window->SkipItems)
238  return;
239 
240  ImGuiContext& g = *GImGui;
241  const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
242  TextUnformatted(g.TempBuffer, text_end);
243 }
244 
245 void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
246 {
247  va_list args;
248  va_start(args, fmt);
249  TextColoredV(col, fmt, args);
250  va_end(args);
251 }
252 
253 void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
254 {
256  TextV(fmt, args);
257  PopStyleColor();
258 }
259 
260 void ImGui::TextDisabled(const char* fmt, ...)
261 {
262  va_list args;
263  va_start(args, fmt);
264  TextDisabledV(fmt, args);
265  va_end(args);
266 }
267 
268 void ImGui::TextDisabledV(const char* fmt, va_list args)
269 {
271  TextV(fmt, args);
272  PopStyleColor();
273 }
274 
275 void ImGui::TextWrapped(const char* fmt, ...)
276 {
277  va_list args;
278  va_start(args, fmt);
279  TextWrappedV(fmt, args);
280  va_end(args);
281 }
282 
283 void ImGui::TextWrappedV(const char* fmt, va_list args)
284 {
285  bool need_backup = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
286  if (need_backup)
287  PushTextWrapPos(0.0f);
288  TextV(fmt, args);
289  if (need_backup)
290  PopTextWrapPos();
291 }
292 
293 void ImGui::LabelText(const char* label, const char* fmt, ...)
294 {
295  va_list args;
296  va_start(args, fmt);
297  LabelTextV(label, fmt, args);
298  va_end(args);
299 }
300 
301 // Add a label+text combo aligned to other label+value widgets
302 void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
303 {
304  ImGuiWindow* window = GetCurrentWindow();
305  if (window->SkipItems)
306  return;
307 
308  ImGuiContext& g = *GImGui;
309  const ImGuiStyle& style = g.Style;
310  const float w = CalcItemWidth();
311 
312  const ImVec2 label_size = CalcTextSize(label, NULL, true);
313  const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
314  const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size);
315  ItemSize(total_bb, style.FramePadding.y);
316  if (!ItemAdd(total_bb, 0))
317  return;
318 
319  // Render
320  const char* value_text_begin = &g.TempBuffer[0];
321  const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
322  RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f));
323  if (label_size.x > 0.0f)
324  RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
325 }
326 
327 void ImGui::BulletText(const char* fmt, ...)
328 {
329  va_list args;
330  va_start(args, fmt);
331  BulletTextV(fmt, args);
332  va_end(args);
333 }
334 
335 // Text with a little bullet aligned to the typical tree node.
336 void ImGui::BulletTextV(const char* fmt, va_list args)
337 {
338  ImGuiWindow* window = GetCurrentWindow();
339  if (window->SkipItems)
340  return;
341 
342  ImGuiContext& g = *GImGui;
343  const ImGuiStyle& style = g.Style;
344 
345  const char* text_begin = g.TempBuffer;
346  const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
347  const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
348  const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
349  const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
350  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding
351  ItemSize(bb);
352  if (!ItemAdd(bb, 0))
353  return;
354 
355  // Render
356  RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
357  RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false);
358 }
359 
360 //-------------------------------------------------------------------------
361 // [SECTION] Widgets: Main
362 //-------------------------------------------------------------------------
363 // - ButtonBehavior() [Internal]
364 // - Button()
365 // - SmallButton()
366 // - InvisibleButton()
367 // - ArrowButton()
368 // - CloseButton() [Internal]
369 // - CollapseButton() [Internal]
370 // - Scrollbar() [Internal]
371 // - Image()
372 // - ImageButton()
373 // - Checkbox()
374 // - CheckboxFlags()
375 // - RadioButton()
376 // - ProgressBar()
377 // - Bullet()
378 //-------------------------------------------------------------------------
379 
380 bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
381 {
382  ImGuiContext& g = *GImGui;
383  ImGuiWindow* window = GetCurrentWindow();
384 
385  if (flags & ImGuiButtonFlags_Disabled)
386  {
387  if (out_hovered) *out_hovered = false;
388  if (out_held) *out_held = false;
389  if (g.ActiveId == id) ClearActiveID();
390  return false;
391  }
392 
393  // Default behavior requires click+release on same spot
396 
397  ImGuiWindow* backup_hovered_window = g.HoveredWindow;
398  if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window)
399  g.HoveredWindow = window;
400 
401 #ifdef IMGUI_ENABLE_TEST_ENGINE
402  if (id != 0 && window->DC.LastItemId != id)
403  ImGuiTestEngineHook_ItemAdd(&g, bb, id);
404 #endif
405 
406  bool pressed = false;
407  bool hovered = ItemHoverable(bb, id);
408 
409  // Drag source doesn't report as hovered
411  hovered = false;
412 
413  // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button
416  {
417  hovered = true;
418  SetHoveredID(id);
419  if (CalcTypematicPressedRepeatAmount(g.HoveredIdTimer + 0.0001f, g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, 0.01f, 0.70f)) // FIXME: Our formula for CalcTypematicPressedRepeatAmount() is fishy
420  {
421  pressed = true;
422  FocusWindow(window);
423  }
424  }
425 
426  if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window)
427  g.HoveredWindow = backup_hovered_window;
428 
429  // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one.
430  if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0))
431  hovered = false;
432 
433  // Mouse
434  if (hovered)
435  {
436  if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
437  {
438  // | CLICKING | HOLDING with ImGuiButtonFlags_Repeat
439  // PressedOnClickRelease | <on release>* | <on repeat> <on repeat> .. (NOT on release) <-- MOST COMMON! (*) only if both click/release were over bounds
440  // PressedOnClick | <on click> | <on click> <on repeat> <on repeat> ..
441  // PressedOnRelease | <on release> | <on repeat> <on repeat> .. (NOT on release)
442  // PressedOnDoubleClick | <on dclick> | <on dclick> <on repeat> <on repeat> ..
443  // FIXME-NAV: We don't honor those different behaviors.
445  {
446  SetActiveID(id, window);
447  if (!(flags & ImGuiButtonFlags_NoNavFocus))
448  SetFocusID(id, window);
449  FocusWindow(window);
450  }
452  {
453  pressed = true;
455  ClearActiveID();
456  else
457  SetActiveID(id, window); // Hold on ID
458  FocusWindow(window);
459  }
460  if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0])
461  {
462  if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps <on release>
463  pressed = true;
464  ClearActiveID();
465  }
466 
467  // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above).
468  // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings.
469  if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && IsMouseClicked(0, true))
470  pressed = true;
471  }
472 
473  if (pressed)
474  g.NavDisableHighlight = true;
475  }
476 
477  // Gamepad/Keyboard navigation
478  // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse.
479  if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId))
480  hovered = true;
481 
482  if (g.NavActivateDownId == id)
483  {
484  bool nav_activated_by_code = (g.NavActivateId == id);
486  if (nav_activated_by_code || nav_activated_by_inputs)
487  pressed = true;
488  if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id)
489  {
490  // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
491  g.NavActivateId = id; // This is so SetActiveId assign a Nav source
492  SetActiveID(id, window);
493  if ((nav_activated_by_code || nav_activated_by_inputs) && !(flags & ImGuiButtonFlags_NoNavFocus))
494  SetFocusID(id, window);
495  g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
496  }
497  }
498 
499  bool held = false;
500  if (g.ActiveId == id)
501  {
503  {
505  g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
506  if (g.IO.MouseDown[0])
507  {
508  held = true;
509  }
510  else
511  {
512  if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease))
513  if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps <on release>
514  if (!g.DragDropActive)
515  pressed = true;
516  ClearActiveID();
517  }
518  if (!(flags & ImGuiButtonFlags_NoNavFocus))
519  g.NavDisableHighlight = true;
520  }
521  else if (g.ActiveIdSource == ImGuiInputSource_Nav)
522  {
523  if (g.NavActivateDownId != id)
524  ClearActiveID();
525  }
526  }
527 
528  if (out_hovered) *out_hovered = hovered;
529  if (out_held) *out_held = held;
530 
531  return pressed;
532 }
533 
534 bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags)
535 {
536  ImGuiWindow* window = GetCurrentWindow();
537  if (window->SkipItems)
538  return false;
539 
540  ImGuiContext& g = *GImGui;
541  const ImGuiStyle& style = g.Style;
542  const ImGuiID id = window->GetID(label);
543  const ImVec2 label_size = CalcTextSize(label, NULL, true);
544 
545  ImVec2 pos = window->DC.CursorPos;
546  if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
547  pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y;
548  ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
549 
550  const ImRect bb(pos, pos + size);
551  ItemSize(size, style.FramePadding.y);
552  if (!ItemAdd(bb, id))
553  return false;
554 
556  flags |= ImGuiButtonFlags_Repeat;
557  bool hovered, held;
558  bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
559  if (pressed)
560  MarkItemEdited(id);
561 
562  // Render
563  const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
564  RenderNavHighlight(bb, id);
565  RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
566  RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
567 
568  // Automatically close popups
569  //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
570  // CloseCurrentPopup();
571 
572  return pressed;
573 }
574 
575 bool ImGui::Button(const char* label, const ImVec2& size_arg)
576 {
577  return ButtonEx(label, size_arg, 0);
578 }
579 
580 // Small buttons fits within text without additional vertical spacing.
581 bool ImGui::SmallButton(const char* label)
582 {
583  ImGuiContext& g = *GImGui;
584  float backup_padding_y = g.Style.FramePadding.y;
585  g.Style.FramePadding.y = 0.0f;
586  bool pressed = ButtonEx(label, ImVec2(0, 0), ImGuiButtonFlags_AlignTextBaseLine);
587  g.Style.FramePadding.y = backup_padding_y;
588  return pressed;
589 }
590 
591 // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack.
592 // Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id)
593 bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg)
594 {
595  ImGuiWindow* window = GetCurrentWindow();
596  if (window->SkipItems)
597  return false;
598 
599  // Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size.
600  IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f);
601 
602  const ImGuiID id = window->GetID(str_id);
603  ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
604  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
605  ItemSize(size);
606  if (!ItemAdd(bb, id))
607  return false;
608 
609  bool hovered, held;
610  bool pressed = ButtonBehavior(bb, id, &hovered, &held);
611 
612  return pressed;
613 }
614 
615 bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags)
616 {
617  ImGuiWindow* window = GetCurrentWindow();
618  if (window->SkipItems)
619  return false;
620 
621  ImGuiContext& g = *GImGui;
622  const ImGuiID id = window->GetID(str_id);
623  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
624  const float default_size = GetFrameHeight();
625  ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f);
626  if (!ItemAdd(bb, id))
627  return false;
628 
630  flags |= ImGuiButtonFlags_Repeat;
631 
632  bool hovered, held;
633  bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
634 
635  // Render
636  const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
637  RenderNavHighlight(bb, id);
638  RenderFrame(bb.Min, bb.Max, col, true, g.Style.FrameRounding);
639  RenderArrow(bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), dir);
640 
641  return pressed;
642 }
643 
644 bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir)
645 {
646  float sz = GetFrameHeight();
647  return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), 0);
648 }
649 
650 // Button to close a window
651 bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius)
652 {
653  ImGuiContext& g = *GImGui;
654  ImGuiWindow* window = g.CurrentWindow;
655 
656  // We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window.
657  // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
658  const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius));
659  bool is_clipped = !ItemAdd(bb, id);
660 
661  bool hovered, held;
662  bool pressed = ButtonBehavior(bb, id, &hovered, &held);
663  if (is_clipped)
664  return pressed;
665 
666  // Render
667  ImVec2 center = bb.GetCenter();
668  if (hovered)
669  window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered), 9);
670 
671  float cross_extent = (radius * 0.7071f) - 1.0f;
672  ImU32 cross_col = GetColorU32(ImGuiCol_Text);
673  center -= ImVec2(0.5f, 0.5f);
674  window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), cross_col, 1.0f);
675  window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), cross_col, 1.0f);
676 
677  return pressed;
678 }
679 
681 {
682  ImGuiContext& g = *GImGui;
683  ImGuiWindow* window = g.CurrentWindow;
684 
685  ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
686  ItemAdd(bb, id);
687  bool hovered, held;
688  bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None);
689 
690  ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
691  if (hovered || held)
692  window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0.0f, -0.5f), g.FontSize * 0.5f + 1.0f, col, 9);
694 
695  // Switch to moving the window after mouse is moved beyond the initial drag threshold
696  if (IsItemActive() && IsMouseDragging())
697  StartMouseMovingWindow(window);
698 
699  return pressed;
700 }
701 
702 // Vertical/Horizontal scrollbar
703 // The entire piece of code below is rather confusing because:
704 // - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab)
705 // - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
706 // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
708 {
709  ImGuiContext& g = *GImGui;
710  ImGuiWindow* window = g.CurrentWindow;
711 
712  const bool horizontal = (direction == ImGuiLayoutType_Horizontal);
713  const ImGuiStyle& style = g.Style;
714  const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY");
715 
716  // Render background
717  bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX);
718  float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f;
719  const ImRect window_rect = window->Rect();
720  const float border_size = window->WindowBorderSize;
721  ImRect bb = horizontal
722  ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size)
723  : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size);
724  if (!horizontal)
725  bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f);
726  if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f)
727  return;
728 
729  int window_rounding_corners;
730  if (horizontal)
731  window_rounding_corners = ImDrawCornerFlags_BotLeft | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight);
732  else
733  window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0) | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight);
734  window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_ScrollbarBg), window->WindowRounding, window_rounding_corners);
735  bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f)));
736 
737  // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar)
738  float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight();
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;
741  float win_size_contents_v = horizontal ? window->SizeContents.x : window->SizeContents.y;
742 
743  // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount)
744  // But we maintain a minimum size in pixel to allow for the user to still aim inside.
745  IM_ASSERT(ImMax(win_size_contents_v, win_size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
746  const float win_size_v = ImMax(ImMax(win_size_contents_v, win_size_avail_v), 1.0f);
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;
749 
750  // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
751  bool held = false;
752  bool hovered = false;
753  const bool previously_held = (g.ActiveId == id);
754  ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
755 
756  float scroll_max = ImMax(1.0f, 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.0f)
760  {
761  float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y;
762  float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y;
763  float* click_delta_to_grab_center_v = horizontal ? &g.ScrollbarClickDeltaToGrabCenter.x : &g.ScrollbarClickDeltaToGrabCenter.y;
764 
765  // Click position in scrollbar normalized space (0.0f->1.0f)
766  const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
767  SetHoveredID(id);
768 
769  bool seek_absolute = false;
770  if (!previously_held)
771  {
772  // On initial click calculate the distance between mouse and the center of the grab
773  if (clicked_v_norm >= grab_v_norm && clicked_v_norm <= grab_v_norm + grab_h_norm)
774  {
775  *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f;
776  }
777  else
778  {
779  seek_absolute = true;
780  *click_delta_to_grab_center_v = 0.0f;
781  }
782  }
783 
784  // Apply scroll
785  // It is ok to modify Scroll here because we are being called in Begin() after the calculation of SizeContents and before setting up our starting position
786  const float scroll_v_norm = ImSaturate((clicked_v_norm - *click_delta_to_grab_center_v - grab_h_norm*0.5f) / (1.0f - grab_h_norm));
787  scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));
788  if (horizontal)
789  window->Scroll.x = scroll_v;
790  else
791  window->Scroll.y = scroll_v;
792 
793  // Update values for rendering
794  scroll_ratio = ImSaturate(scroll_v / scroll_max);
795  grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
796 
797  // Update distance to grab now that we have seeked and saturated
798  if (seek_absolute)
799  *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f;
800  }
801 
802  // Render
804  ImRect grab_rect;
805  if (horizontal)
806  grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImMin(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, window_rect.Max.x), bb.Max.y);
807  else
808  grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImMin(ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels, window_rect.Max.y));
809  window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding);
810 }
811 
812 void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
813 {
814  ImGuiWindow* window = GetCurrentWindow();
815  if (window->SkipItems)
816  return;
817 
818  ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
819  if (border_col.w > 0.0f)
820  bb.Max += ImVec2(2, 2);
821  ItemSize(bb);
822  if (!ItemAdd(bb, 0))
823  return;
824 
825  if (border_col.w > 0.0f)
826  {
827  window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f);
828  window->DrawList->AddImage(user_texture_id, bb.Min + ImVec2(1, 1), bb.Max - ImVec2(1, 1), uv0, uv1, GetColorU32(tint_col));
829  }
830  else
831  {
832  window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col));
833  }
834 }
835 
836 // frame_padding < 0: uses FramePadding from style (default)
837 // frame_padding = 0: no framing
838 // frame_padding > 0: set framing size
839 // The color used are the button colors.
840 bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col)
841 {
842  ImGuiWindow* window = GetCurrentWindow();
843  if (window->SkipItems)
844  return false;
845 
846  ImGuiContext& g = *GImGui;
847  const ImGuiStyle& style = g.Style;
848 
849  // Default to using texture ID as ID. User can still push string/integer prefixes.
850  // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV.
851  PushID((void*)(intptr_t)user_texture_id);
852  const ImGuiID id = window->GetID("#image");
853  PopID();
854 
855  const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;
856  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2);
857  const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size);
858  ItemSize(bb);
859  if (!ItemAdd(bb, id))
860  return false;
861 
862  bool hovered, held;
863  bool pressed = ButtonBehavior(bb, id, &hovered, &held);
864 
865  // Render
866  const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
867  RenderNavHighlight(bb, id);
868  RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding));
869  if (bg_col.w > 0.0f)
870  window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col));
871  window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col));
872 
873  return pressed;
874 }
875 
876 bool ImGui::Checkbox(const char* label, bool* v)
877 {
878  ImGuiWindow* window = GetCurrentWindow();
879  if (window->SkipItems)
880  return false;
881 
882  ImGuiContext& g = *GImGui;
883  const ImGuiStyle& style = g.Style;
884  const ImGuiID id = window->GetID(label);
885  const ImVec2 label_size = CalcTextSize(label, NULL, true);
886 
887  const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2, label_size.y + style.FramePadding.y*2)); // We want a square shape to we use Y twice
888  ItemSize(check_bb, style.FramePadding.y);
889 
890  ImRect total_bb = check_bb;
891  if (label_size.x > 0)
892  SameLine(0, style.ItemInnerSpacing.x);
893  const ImRect text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size);
894  if (label_size.x > 0)
895  {
896  ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y);
897  total_bb = ImRect(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max));
898  }
899 
900  if (!ItemAdd(total_bb, id))
901  return false;
902 
903  bool hovered, held;
904  bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
905  if (pressed)
906  {
907  *v = !(*v);
908  MarkItemEdited(id);
909  }
910 
911  RenderNavHighlight(total_bb, id);
912  RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
913  if (*v)
914  {
915  const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
916  const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f));
917  RenderCheckMark(check_bb.Min + ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), check_bb.GetWidth() - pad*2.0f);
918  }
919 
920  if (g.LogEnabled)
921  LogRenderedText(&text_bb.Min, *v ? "[x]" : "[ ]");
922  if (label_size.x > 0.0f)
923  RenderText(text_bb.Min, label);
924 
925  IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
926  return pressed;
927 }
928 
929 bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value)
930 {
931  bool v = ((*flags & flags_value) == flags_value);
932  bool pressed = Checkbox(label, &v);
933  if (pressed)
934  {
935  if (v)
936  *flags |= flags_value;
937  else
938  *flags &= ~flags_value;
939  }
940 
941  return pressed;
942 }
943 
944 bool ImGui::RadioButton(const char* label, bool active)
945 {
946  ImGuiWindow* window = GetCurrentWindow();
947  if (window->SkipItems)
948  return false;
949 
950  ImGuiContext& g = *GImGui;
951  const ImGuiStyle& style = g.Style;
952  const ImGuiID id = window->GetID(label);
953  const ImVec2 label_size = CalcTextSize(label, NULL, true);
954 
955  const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2-1, label_size.y + style.FramePadding.y*2-1));
956  ItemSize(check_bb, style.FramePadding.y);
957 
958  ImRect total_bb = check_bb;
959  if (label_size.x > 0)
960  SameLine(0, style.ItemInnerSpacing.x);
961  const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size);
962  if (label_size.x > 0)
963  {
964  ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y);
965  total_bb.Add(text_bb);
966  }
967 
968  if (!ItemAdd(total_bb, id))
969  return false;
970 
971  ImVec2 center = check_bb.GetCenter();
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;
975 
976  bool hovered, held;
977  bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
978  if (pressed)
979  MarkItemEdited(id);
980 
981  RenderNavHighlight(total_bb, id);
982  window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
983  if (active)
984  {
985  const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
986  const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f));
987  window->DrawList->AddCircleFilled(center, radius-pad, GetColorU32(ImGuiCol_CheckMark), 16);
988  }
989 
990  if (style.FrameBorderSize > 0.0f)
991  {
992  window->DrawList->AddCircle(center+ImVec2(1,1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize);
993  window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize);
994  }
995 
996  if (g.LogEnabled)
997  LogRenderedText(&text_bb.Min, active ? "(x)" : "( )");
998  if (label_size.x > 0.0f)
999  RenderText(text_bb.Min, label);
1000 
1001  return pressed;
1002 }
1003 
1004 bool ImGui::RadioButton(const char* label, int* v, int v_button)
1005 {
1006  const bool pressed = RadioButton(label, *v == v_button);
1007  if (pressed)
1008  *v = v_button;
1009  return pressed;
1010 }
1011 
1012 // size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size
1013 void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay)
1014 {
1015  ImGuiWindow* window = GetCurrentWindow();
1016  if (window->SkipItems)
1017  return;
1018 
1019  ImGuiContext& g = *GImGui;
1020  const ImGuiStyle& style = g.Style;
1021 
1022  ImVec2 pos = window->DC.CursorPos;
1023  ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f));
1024  ItemSize(bb, style.FramePadding.y);
1025  if (!ItemAdd(bb, 0))
1026  return;
1027 
1028  // Render
1029  fraction = ImSaturate(fraction);
1031  bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize));
1032  const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y);
1034 
1035  // Default displaying the fraction as percentage string, but user can override it
1036  char overlay_buf[32];
1037  if (!overlay)
1038  {
1039  ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction*100+0.01f);
1040  overlay = overlay_buf;
1041  }
1042 
1043  ImVec2 overlay_size = CalcTextSize(overlay, NULL);
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.0f,0.5f), &bb);
1046 }
1047 
1049 {
1050  ImGuiWindow* window = GetCurrentWindow();
1051  if (window->SkipItems)
1052  return;
1053 
1054  ImGuiContext& g = *GImGui;
1055  const ImGuiStyle& style = g.Style;
1056  const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
1057  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height));
1058  ItemSize(bb);
1059  if (!ItemAdd(bb, 0))
1060  {
1061  SameLine(0, style.FramePadding.x*2);
1062  return;
1063  }
1064 
1065  // Render and stay on same line
1066  RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
1067  SameLine(0, style.FramePadding.x*2);
1068 }
1069 
1070 //-------------------------------------------------------------------------
1071 // [SECTION] Widgets: Low-level Layout helpers
1072 //-------------------------------------------------------------------------
1073 // - Spacing()
1074 // - Dummy()
1075 // - NewLine()
1076 // - AlignTextToFramePadding()
1077 // - Separator()
1078 // - VerticalSeparator() [Internal]
1079 // - SplitterBehavior() [Internal]
1080 //-------------------------------------------------------------------------
1081 
1083 {
1084  ImGuiWindow* window = GetCurrentWindow();
1085  if (window->SkipItems)
1086  return;
1087  ItemSize(ImVec2(0,0));
1088 }
1089 
1090 void ImGui::Dummy(const ImVec2& size)
1091 {
1092  ImGuiWindow* window = GetCurrentWindow();
1093  if (window->SkipItems)
1094  return;
1095 
1096  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
1097  ItemSize(bb);
1098  ItemAdd(bb, 0);
1099 }
1100 
1102 {
1103  ImGuiWindow* window = GetCurrentWindow();
1104  if (window->SkipItems)
1105  return;
1106 
1107  ImGuiContext& g = *GImGui;
1108  const ImGuiLayoutType backup_layout_type = window->DC.LayoutType;
1110  if (window->DC.CurrentLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
1111  ItemSize(ImVec2(0,0));
1112  else
1113  ItemSize(ImVec2(0.0f, g.FontSize));
1114  window->DC.LayoutType = backup_layout_type;
1115 }
1116 
1118 {
1119  ImGuiWindow* window = GetCurrentWindow();
1120  if (window->SkipItems)
1121  return;
1122 
1123  ImGuiContext& g = *GImGui;
1124  window->DC.CurrentLineSize.y = ImMax(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y * 2);
1126 }
1127 
1128 // Horizontal/vertical separating line
1130 {
1131  ImGuiWindow* window = GetCurrentWindow();
1132  if (window->SkipItems)
1133  return;
1134  ImGuiContext& g = *GImGui;
1135 
1136  // Those flags should eventually be overridable by the user
1138  IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected
1139  if (flags & ImGuiSeparatorFlags_Vertical)
1140  {
1142  return;
1143  }
1144 
1145  // Horizontal Separator
1146  if (window->DC.ColumnsSet)
1147  PopClipRect();
1148 
1149  float x1 = window->Pos.x;
1150  float x2 = window->Pos.x + window->Size.x;
1151  if (!window->DC.GroupStack.empty())
1152  x1 += window->DC.Indent.x;
1153 
1154  const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f));
1155  ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout.
1156  if (!ItemAdd(bb, 0))
1157  {
1158  if (window->DC.ColumnsSet)
1160  return;
1161  }
1162 
1163  window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Separator));
1164 
1165  if (g.LogEnabled)
1166  LogRenderedText(&bb.Min, "--------------------------------");
1167 
1168  if (window->DC.ColumnsSet)
1169  {
1171  window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y;
1172  }
1173 }
1174 
1176 {
1177  ImGuiWindow* window = GetCurrentWindow();
1178  if (window->SkipItems)
1179  return;
1180  ImGuiContext& g = *GImGui;
1181 
1182  float y1 = window->DC.CursorPos.y;
1183  float y2 = window->DC.CursorPos.y + window->DC.CurrentLineSize.y;
1184  const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + 1.0f, y2));
1185  ItemSize(ImVec2(bb.GetWidth(), 0.0f));
1186  if (!ItemAdd(bb, 0))
1187  return;
1188 
1189  window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
1190  if (g.LogEnabled)
1191  LogText(" |");
1192 }
1193 
1194 // Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise.
1195 bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay)
1196 {
1197  ImGuiContext& g = *GImGui;
1198  ImGuiWindow* window = g.CurrentWindow;
1199 
1200  const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
1202  bool item_add = ItemAdd(bb, id);
1203  window->DC.ItemFlags = item_flags_backup;
1204  if (!item_add)
1205  return false;
1206 
1207  bool hovered, held;
1208  ImRect bb_interact = bb;
1209  bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f));
1211  if (g.ActiveId != id)
1213 
1214  if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay))
1216 
1217  ImRect bb_render = bb;
1218  if (held)
1219  {
1220  ImVec2 mouse_delta_2d = g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min;
1221  float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x;
1222 
1223  // Minimum pane size
1224  float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1);
1225  float size_2_maximum_delta = ImMax(0.0f, *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;
1230 
1231  // Apply resize
1232  if (mouse_delta != 0.0f)
1233  {
1234  if (mouse_delta < 0.0f)
1235  IM_ASSERT(*size1 + mouse_delta >= min_size1);
1236  if (mouse_delta > 0.0f)
1237  IM_ASSERT(*size2 - mouse_delta >= min_size2);
1238  *size1 += mouse_delta;
1239  *size2 -= mouse_delta;
1240  bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta));
1241  MarkItemEdited(id);
1242  }
1243  }
1244 
1245  // Render
1246  const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
1247  window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, g.Style.FrameRounding);
1248 
1249  return held;
1250 }
1251 
1252 //-------------------------------------------------------------------------
1253 // [SECTION] Widgets: ComboBox
1254 //-------------------------------------------------------------------------
1255 // - BeginCombo()
1256 // - EndCombo()
1257 // - Combo()
1258 //-------------------------------------------------------------------------
1259 
1260 static float CalcMaxPopupHeightFromItemCount(int items_count)
1261 {
1262  ImGuiContext& g = *GImGui;
1263  if (items_count <= 0)
1264  return FLT_MAX;
1265  return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2);
1266 }
1267 
1268 bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags)
1269 {
1270  // Always consume the SetNextWindowSizeConstraint() call in our early return paths
1271  ImGuiContext& g = *GImGui;
1272  ImGuiCond backup_next_window_size_constraint = g.NextWindowData.SizeConstraintCond;
1274 
1275  ImGuiWindow* window = GetCurrentWindow();
1276  if (window->SkipItems)
1277  return false;
1278 
1280 
1281  const ImGuiStyle& style = g.Style;
1282  const ImGuiID id = window->GetID(label);
1283 
1284  const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
1285  const ImVec2 label_size = CalcTextSize(label, NULL, true);
1286  const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth();
1287  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
1288  const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
1289  ItemSize(total_bb, style.FramePadding.y);
1290  if (!ItemAdd(total_bb, id, &frame_bb))
1291  return false;
1292 
1293  bool hovered, held;
1294  bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);
1295  bool popup_open = IsPopupOpen(id);
1296 
1297  const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f));
1298  const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
1299  RenderNavHighlight(frame_bb, id);
1300  if (!(flags & ImGuiComboFlags_NoPreview))
1301  window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Max.y), frame_col, style.FrameRounding, ImDrawCornerFlags_Left);
1302  if (!(flags & ImGuiComboFlags_NoArrowButton))
1303  {
1304  window->DrawList->AddRectFilled(ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button), style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right);
1305  RenderArrow(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down);
1306  }
1307  RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding);
1308  if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
1309  RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f));
1310  if (label_size.x > 0)
1311  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
1312 
1313  if ((pressed || g.NavActivateId == id) && !popup_open)
1314  {
1315  if (window->DC.NavLayerCurrent == 0)
1316  window->NavLastIds[0] = id;
1317  OpenPopupEx(id);
1318  popup_open = true;
1319  }
1320 
1321  if (!popup_open)
1322  return false;
1323 
1324  if (backup_next_window_size_constraint)
1325  {
1326  g.NextWindowData.SizeConstraintCond = backup_next_window_size_constraint;
1328  }
1329  else
1330  {
1331  if ((flags & ImGuiComboFlags_HeightMask_) == 0)
1334  int popup_max_height_in_items = -1;
1335  if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
1336  else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
1337  else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
1338  SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
1339  }
1340 
1341  char name[16];
1342  ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
1343 
1344  // Peak into expected window size so we can position it
1345  if (ImGuiWindow* popup_window = FindWindowByName(name))
1346  if (popup_window->WasActive)
1347  {
1348  ImVec2 size_expected = CalcWindowExpectedSize(popup_window);
1349  if (flags & ImGuiComboFlags_PopupAlignLeft)
1350  popup_window->AutoPosLastDirection = ImGuiDir_Left;
1351  ImRect r_outer = GetWindowAllowedExtentRect(popup_window);
1352  ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox);
1353  SetNextWindowPos(pos);
1354  }
1355 
1356  // Horizontally align ourselves with the framed text
1359  bool ret = Begin(name, NULL, window_flags);
1360  PopStyleVar();
1361  if (!ret)
1362  {
1363  EndPopup();
1364  IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
1365  return false;
1366  }
1367  return true;
1368 }
1369 
1371 {
1372  EndPopup();
1373 }
1374 
1375 // Getter for the old Combo() API: const char*[]
1376 static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
1377 {
1378  const char* const* items = (const char* const*)data;
1379  if (out_text)
1380  *out_text = items[idx];
1381  return true;
1382 }
1383 
1384 // Getter for the old Combo() API: "item1\0item2\0item3\0"
1385 static bool Items_SingleStringGetter(void* data, int idx, const char** out_text)
1386 {
1387  // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited.
1388  const char* items_separated_by_zeros = (const char*)data;
1389  int items_count = 0;
1390  const char* p = items_separated_by_zeros;
1391  while (*p)
1392  {
1393  if (idx == items_count)
1394  break;
1395  p += strlen(p) + 1;
1396  items_count++;
1397  }
1398  if (!*p)
1399  return false;
1400  if (out_text)
1401  *out_text = p;
1402  return true;
1403 }
1404 
1405 // Old API, prefer using BeginCombo() nowadays if you can.
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)
1407 {
1408  ImGuiContext& g = *GImGui;
1409 
1410  // Call the getter to obtain the preview string which is a parameter to BeginCombo()
1411  const char* preview_value = NULL;
1412  if (*current_item >= 0 && *current_item < items_count)
1413  items_getter(data, *current_item, &preview_value);
1414 
1415  // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
1416  if (popup_max_height_in_items != -1 && !g.NextWindowData.SizeConstraintCond)
1417  SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
1418 
1419  if (!BeginCombo(label, preview_value, ImGuiComboFlags_None))
1420  return false;
1421 
1422  // Display items
1423  // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
1424  bool value_changed = false;
1425  for (int i = 0; i < items_count; i++)
1426  {
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*";
1432  if (Selectable(item_text, item_selected))
1433  {
1434  value_changed = true;
1435  *current_item = i;
1436  }
1437  if (item_selected)
1439  PopID();
1440  }
1441 
1442  EndCombo();
1443  return value_changed;
1444 }
1445 
1446 // Combo box helper allowing to pass an array of strings.
1447 bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items)
1448 {
1449  const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items);
1450  return value_changed;
1451 }
1452 
1453 // Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0"
1454 bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
1455 {
1456  int items_count = 0;
1457  const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open
1458  while (*p)
1459  {
1460  p += strlen(p) + 1;
1461  items_count++;
1462  }
1463  bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items);
1464  return value_changed;
1465 }
1466 
1467 //-------------------------------------------------------------------------
1468 // [SECTION] Data Type and Data Formatting Helpers [Internal]
1469 //-------------------------------------------------------------------------
1470 // - PatchFormatStringFloatToInt()
1471 // - DataTypeFormatString()
1472 // - DataTypeApplyOp()
1473 // - DataTypeApplyOpFromText()
1474 // - GetMinimumStepAtDecimalPrecision
1475 // - RoundScalarWithFormat<>()
1476 //-------------------------------------------------------------------------
1477 
1479 {
1480  size_t Size;
1481  const char* PrintFmt; // Unused
1482  const char* ScanFmt;
1483 };
1484 
1486 {
1487  { sizeof(int), "%d", "%d" },
1488  { sizeof(unsigned int), "%u", "%u" },
1489 #ifdef _MSC_VER
1490  { sizeof(ImS64), "%I64d","%I64d" },
1491  { sizeof(ImU64), "%I64u","%I64u" },
1492 #else
1493  { sizeof(ImS64), "%lld", "%lld" },
1494  { sizeof(ImU64), "%llu", "%llu" },
1495 #endif
1496  { sizeof(float), "%f", "%f" }, // float are promoted to double in va_arg
1497  { sizeof(double), "%f", "%lf" },
1498 };
1500 
1501 // FIXME-LEGACY: Prior to 1.61 our DragInt() function internally used floats and because of this the compile-time default value for format was "%.0f".
1502 // Even though we changed the compile-time default, we expect users to have carried %f around, which would break the display of DragInt() calls.
1503 // To honor backward compatibility we are rewriting the format string, unless IMGUI_DISABLE_OBSOLETE_FUNCTIONS is enabled. What could possibly go wrong?!
1504 static const char* PatchFormatStringFloatToInt(const char* fmt)
1505 {
1506  if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '0' && fmt[3] == 'f' && fmt[4] == 0) // Fast legacy path for "%.0f" which is expected to be the most common case.
1507  return "%d";
1508  const char* fmt_start = ImParseFormatFindStart(fmt); // Find % (if any, and ignore %%)
1509  const char* fmt_end = ImParseFormatFindEnd(fmt_start); // Find end of format specifier, which itself is an exercise of confidence/recklessness (because snprintf is dependent on libc or user).
1510  if (fmt_end > fmt_start && fmt_end[-1] == 'f')
1511  {
1512 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1513  if (fmt_start == fmt && fmt_end[0] == 0)
1514  return "%d";
1515  ImGuiContext& g = *GImGui;
1516  ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%.*s%%d%s", (int)(fmt_start - fmt), fmt, fmt_end); // Honor leading and trailing decorations, but lose alignment/precision.
1517  return g.TempBuffer;
1518 #else
1519  IM_ASSERT(0 && "DragInt(): Invalid format string!"); // Old versions used a default parameter of "%.0f", please replace with e.g. "%d"
1520 #endif
1521  }
1522  return fmt;
1523 }
1524 
1525 static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format)
1526 {
1527  if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32) // Signedness doesn't matter when pushing the argument
1528  return ImFormatString(buf, buf_size, format, *(const ImU32*)data_ptr);
1529  if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) // Signedness doesn't matter when pushing the argument
1530  return ImFormatString(buf, buf_size, format, *(const ImU64*)data_ptr);
1531  if (data_type == ImGuiDataType_Float)
1532  return ImFormatString(buf, buf_size, format, *(const float*)data_ptr);
1533  if (data_type == ImGuiDataType_Double)
1534  return ImFormatString(buf, buf_size, format, *(const double*)data_ptr);
1535  IM_ASSERT(0);
1536  return 0;
1537 }
1538 
1539 // FIXME: Adding support for clamping on boundaries of the data type would be nice.
1540 static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2)
1541 {
1542  IM_ASSERT(op == '+' || op == '-');
1543  switch (data_type)
1544  {
1545  case ImGuiDataType_S32:
1546  if (op == '+') *(int*)output = *(const int*)arg1 + *(const int*)arg2;
1547  else if (op == '-') *(int*)output = *(const int*)arg1 - *(const int*)arg2;
1548  return;
1549  case ImGuiDataType_U32:
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;
1552  return;
1553  case ImGuiDataType_S64:
1554  if (op == '+') *(ImS64*)output = *(const ImS64*)arg1 + *(const ImS64*)arg2;
1555  else if (op == '-') *(ImS64*)output = *(const ImS64*)arg1 - *(const ImS64*)arg2;
1556  return;
1557  case ImGuiDataType_U64:
1558  if (op == '+') *(ImU64*)output = *(const ImU64*)arg1 + *(const ImU64*)arg2;
1559  else if (op == '-') *(ImU64*)output = *(const ImU64*)arg1 - *(const ImU64*)arg2;
1560  return;
1561  case ImGuiDataType_Float:
1562  if (op == '+') *(float*)output = *(const float*)arg1 + *(const float*)arg2;
1563  else if (op == '-') *(float*)output = *(const float*)arg1 - *(const float*)arg2;
1564  return;
1565  case ImGuiDataType_Double:
1566  if (op == '+') *(double*)output = *(const double*)arg1 + *(const double*)arg2;
1567  else if (op == '-') *(double*)output = *(const double*)arg1 - *(const double*)arg2;
1568  return;
1569  case ImGuiDataType_COUNT: break;
1570  }
1571  IM_ASSERT(0);
1572 }
1573 
1574 // User can input math operators (e.g. +100) to edit a numerical values.
1575 // NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
1576 static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format)
1577 {
1578  while (ImCharIsBlankA(*buf))
1579  buf++;
1580 
1581  // We don't support '-' op because it would conflict with inputing negative value.
1582  // Instead you can use +-100 to subtract from an existing value
1583  char op = buf[0];
1584  if (op == '+' || op == '*' || op == '/')
1585  {
1586  buf++;
1587  while (ImCharIsBlankA(*buf))
1588  buf++;
1589  }
1590  else
1591  {
1592  op = 0;
1593  }
1594  if (!buf[0])
1595  return false;
1596 
1597  // Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all.
1598  IM_ASSERT(data_type < ImGuiDataType_COUNT);
1599  int data_backup[2];
1600  IM_ASSERT(GDataTypeInfo[data_type].Size <= sizeof(data_backup));
1601  memcpy(data_backup, data_ptr, GDataTypeInfo[data_type].Size);
1602 
1603  if (format == NULL)
1604  format = GDataTypeInfo[data_type].ScanFmt;
1605 
1606  int arg1i = 0;
1607  if (data_type == ImGuiDataType_S32)
1608  {
1609  int* v = (int*)data_ptr;
1610  int arg0i = *v;
1611  float arg1f = 0.0f;
1612  if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
1613  return false;
1614  // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision
1615  if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); } // Add (use "+-" to subtract)
1616  else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); } // Multiply
1617  else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); } // Divide
1618  else { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; } // Assign constant
1619  }
1620  else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
1621  {
1622  // Assign constant
1623  // FIXME: We don't bother handling support for legacy operators since they are a little too crappy. Instead we may implement a proper expression evaluator in the future.
1624  sscanf(buf, format, data_ptr);
1625  }
1626  else if (data_type == ImGuiDataType_Float)
1627  {
1628  // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
1629  format = "%f";
1630  float* v = (float*)data_ptr;
1631  float arg0f = *v, arg1f = 0.0f;
1632  if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
1633  return false;
1634  if (sscanf(buf, format, &arg1f) < 1)
1635  return false;
1636  if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
1637  else if (op == '*') { *v = arg0f * arg1f; } // Multiply
1638  else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
1639  else { *v = arg1f; } // Assign constant
1640  }
1641  else if (data_type == ImGuiDataType_Double)
1642  {
1643  format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis
1644  double* v = (double*)data_ptr;
1645  double arg0f = *v, arg1f = 0.0;
1646  if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
1647  return false;
1648  if (sscanf(buf, format, &arg1f) < 1)
1649  return false;
1650  if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
1651  else if (op == '*') { *v = arg0f * arg1f; } // Multiply
1652  else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
1653  else { *v = arg1f; } // Assign constant
1654  }
1655  return memcmp(data_backup, data_ptr, GDataTypeInfo[data_type].Size) != 0;
1656 }
1657 
1658 static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
1659 {
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)
1662  return FLT_MIN;
1663  return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision);
1664 }
1665 
1666 template<typename TYPE>
1667 static const char* ImAtoi(const char* src, TYPE* output)
1668 {
1669  int negative = 0;
1670  if (*src == '-') { negative = 1; src++; }
1671  if (*src == '+') { src++; }
1672  TYPE v = 0;
1673  while (*src >= '0' && *src <= '9')
1674  v = (v * 10) + (*src++ - '0');
1675  *output = negative ? -v : v;
1676  return src;
1677 }
1678 
1679 template<typename TYPE, typename SIGNEDTYPE>
1680 TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, TYPE v)
1681 {
1682  const char* fmt_start = ImParseFormatFindStart(format);
1683  if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string
1684  return v;
1685  char v_str[64];
1686  ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v);
1687  const char* p = v_str;
1688  while (*p == ' ')
1689  p++;
1690  if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
1691  v = (TYPE)ImAtof(p);
1692  else
1693  ImAtoi(p, (SIGNEDTYPE*)&v);
1694  return v;
1695 }
1696 
1697 //-------------------------------------------------------------------------
1698 // [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc.
1699 //-------------------------------------------------------------------------
1700 // - DragBehaviorT<>() [Internal]
1701 // - DragBehavior() [Internal]
1702 // - DragScalar()
1703 // - DragScalarN()
1704 // - DragFloat()
1705 // - DragFloat2()
1706 // - DragFloat3()
1707 // - DragFloat4()
1708 // - DragFloatRange2()
1709 // - DragInt()
1710 // - DragInt2()
1711 // - DragInt3()
1712 // - DragInt4()
1713 // - DragIntRange2()
1714 //-------------------------------------------------------------------------
1715 
1716 // This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls)
1717 template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
1718 bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, float power, ImGuiDragFlags flags)
1719 {
1720  ImGuiContext& g = *GImGui;
1721  const ImGuiAxis axis = (flags & ImGuiDragFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
1722  const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
1723  const bool has_min_max = (v_min != v_max);
1724 
1725  // Default tweak speed
1726  if (v_speed == 0.0f && has_min_max && (v_max - v_min < FLT_MAX))
1727  v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio);
1728 
1729  // Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings
1730  float adjust_delta = 0.0f;
1732  {
1733  adjust_delta = g.IO.MouseDelta[axis];
1734  if (g.IO.KeyAlt)
1735  adjust_delta *= 1.0f / 100.0f;
1736  if (g.IO.KeyShift)
1737  adjust_delta *= 10.0f;
1738  }
1739  else if (g.ActiveIdSource == ImGuiInputSource_Nav)
1740  {
1741  int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
1743  v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
1744  }
1745  adjust_delta *= v_speed;
1746 
1747  // For vertical drag we currently assume that Up=higher value (like we do with vertical sliders). This may become a parameter.
1748  if (axis == ImGuiAxis_Y)
1749  adjust_delta = -adjust_delta;
1750 
1751  // Clear current value on activation
1752  // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300.
1753  bool is_just_activated = g.ActiveIdIsJustActivated;
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)
1756  {
1757  g.DragCurrentAccum = 0.0f;
1758  g.DragCurrentAccumDirty = false;
1759  }
1760  else if (adjust_delta != 0.0f)
1761  {
1762  g.DragCurrentAccum += adjust_delta;
1763  g.DragCurrentAccumDirty = true;
1764  }
1765 
1766  if (!g.DragCurrentAccumDirty)
1767  return false;
1768 
1769  TYPE v_cur = *v;
1770  FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f;
1771 
1772  const bool is_power = (power != 1.0f && is_decimal && has_min_max && (v_max - v_min < FLT_MAX));
1773  if (is_power)
1774  {
1775  // Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range
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;
1780  }
1781  else
1782  {
1783  v_cur += (TYPE)g.DragCurrentAccum;
1784  }
1785 
1786  // Round to user desired precision based on format string
1787  v_cur = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_cur);
1788 
1789  // Preserve remainder after rounding has been applied. This also allow slow tweaking of values.
1790  g.DragCurrentAccumDirty = false;
1791  if (is_power)
1792  {
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);
1795  }
1796  else
1797  {
1798  g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*v);
1799  }
1800 
1801  // Lose zero sign for float/double
1802  if (v_cur == (TYPE)-0)
1803  v_cur = (TYPE)0;
1804 
1805  // Clamp values (+ handle overflow/wrap-around for integer types)
1806  if (*v != v_cur && has_min_max)
1807  {
1808  if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_decimal))
1809  v_cur = v_min;
1810  if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_decimal))
1811  v_cur = v_max;
1812  }
1813 
1814  // Apply result
1815  if (*v == v_cur)
1816  return false;
1817  *v = v_cur;
1818  return true;
1819 }
1820 
1821 bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power, ImGuiDragFlags flags)
1822 {
1823  ImGuiContext& g = *GImGui;
1824  if (g.ActiveId == id)
1825  {
1827  ClearActiveID();
1829  ClearActiveID();
1830  }
1831  if (g.ActiveId != id)
1832  return false;
1833 
1834  switch (data_type)
1835  {
1836  case ImGuiDataType_S32: return DragBehaviorT<ImS32, ImS32, float >(data_type, (ImS32*)v, v_speed, v_min ? *(const ImS32* )v_min : IM_S32_MIN, v_max ? *(const ImS32* )v_max : IM_S32_MAX, format, power, flags);
1837  case ImGuiDataType_U32: return DragBehaviorT<ImU32, ImS32, float >(data_type, (ImU32*)v, v_speed, v_min ? *(const ImU32* )v_min : IM_U32_MIN, v_max ? *(const ImU32* )v_max : IM_U32_MAX, format, power, flags);
1838  case ImGuiDataType_S64: return DragBehaviorT<ImS64, ImS64, double>(data_type, (ImS64*)v, v_speed, v_min ? *(const ImS64* )v_min : IM_S64_MIN, v_max ? *(const ImS64* )v_max : IM_S64_MAX, format, power, flags);
1839  case ImGuiDataType_U64: return DragBehaviorT<ImU64, ImS64, double>(data_type, (ImU64*)v, v_speed, v_min ? *(const ImU64* )v_min : IM_U64_MIN, v_max ? *(const ImU64* )v_max : IM_U64_MAX, format, power, flags);
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);
1842  case ImGuiDataType_COUNT: break;
1843  }
1844  IM_ASSERT(0);
1845  return false;
1846 }
1847 
1848 bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power)
1849 {
1850  ImGuiWindow* window = GetCurrentWindow();
1851  if (window->SkipItems)
1852  return false;
1853 
1854  if (power != 1.0f)
1855  IM_ASSERT(v_min != NULL && v_max != NULL); // When using a power curve the drag needs to have known bounds
1856 
1857  ImGuiContext& g = *GImGui;
1858  const ImGuiStyle& style = g.Style;
1859  const ImGuiID id = window->GetID(label);
1860  const float w = CalcItemWidth();
1861 
1862  const ImVec2 label_size = CalcTextSize(label, NULL, true);
1863  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
1864  const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
1865  const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
1866 
1867  // NB- we don't call ItemSize() yet because we may turn into a text edit box below
1868  if (!ItemAdd(total_bb, id, &frame_bb))
1869  {
1870  ItemSize(total_bb, style.FramePadding.y);
1871  return false;
1872  }
1873  const bool hovered = ItemHoverable(frame_bb, id);
1874 
1875  // Default format string when passing NULL
1876  // Patch old "%.0f" format string to use "%d", read function comments for more details.
1877  IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
1878  if (format == NULL)
1879  format = GDataTypeInfo[data_type].PrintFmt;
1880  else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0)
1881  format = PatchFormatStringFloatToInt(format);
1882 
1883  // Tabbing or CTRL-clicking on Drag turns it into an input box
1884  bool start_text_input = false;
1885  const bool tab_focus_requested = FocusableItemRegister(window, id);
1886  if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
1887  {
1888  SetActiveID(id, window);
1889  SetFocusID(id, window);
1890  FocusWindow(window);
1892  if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id)
1893  {
1894  start_text_input = true;
1895  g.ScalarAsInputTextId = 0;
1896  }
1897  }
1898  if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
1899  {
1900  FocusableItemUnregister(window);
1901  return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format);
1902  }
1903 
1904  // Actual drag behavior
1905  ItemSize(total_bb, style.FramePadding.y);
1906  const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power, ImGuiDragFlags_None);
1907  if (value_changed)
1908  MarkItemEdited(id);
1909 
1910  // Draw frame
1912  RenderNavHighlight(frame_bb, id);
1913  RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
1914 
1915  // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
1916  char value_buf[64];
1917  const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format);
1918  RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
1919 
1920  if (label_size.x > 0.0f)
1921  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
1922 
1923  return value_changed;
1924 }
1925 
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)
1927 {
1928  ImGuiWindow* window = GetCurrentWindow();
1929  if (window->SkipItems)
1930  return false;
1931 
1932  ImGuiContext& g = *GImGui;
1933  bool value_changed = false;
1934  BeginGroup();
1935  PushID(label);
1936  PushMultiItemsWidths(components);
1937  size_t type_size = GDataTypeInfo[data_type].Size;
1938  for (int i = 0; i < components; i++)
1939  {
1940  PushID(i);
1941  value_changed |= DragScalar("##v", data_type, v, v_speed, v_min, v_max, format, power);
1943  PopID();
1944  PopItemWidth();
1945  v = (void*)((char*)v + type_size);
1946  }
1947  PopID();
1948 
1949  TextUnformatted(label, FindRenderedTextEnd(label));
1950  EndGroup();
1951  return value_changed;
1952 }
1953 
1954 bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power)
1955 {
1956  return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, power);
1957 }
1958 
1959 bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power)
1960 {
1961  return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, power);
1962 }
1963 
1964 bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power)
1965 {
1966  return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, power);
1967 }
1968 
1969 bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power)
1970 {
1971  return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, power);
1972 }
1973 
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)
1975 {
1976  ImGuiWindow* window = GetCurrentWindow();
1977  if (window->SkipItems)
1978  return false;
1979 
1980  ImGuiContext& g = *GImGui;
1981  PushID(label);
1982  BeginGroup();
1984 
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);
1986  PopItemWidth();
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);
1989  PopItemWidth();
1991 
1992  TextUnformatted(label, FindRenderedTextEnd(label));
1993  EndGroup();
1994  PopID();
1995  return value_changed;
1996 }
1997 
1998 // NB: v_speed is float to allow adjusting the drag speed with more precision
1999 bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format)
2000 {
2001  return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format);
2002 }
2003 
2004 bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format)
2005 {
2006  return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format);
2007 }
2008 
2009 bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format)
2010 {
2011  return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format);
2012 }
2013 
2014 bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format)
2015 {
2016  return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format);
2017 }
2018 
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)
2020 {
2021  ImGuiWindow* window = GetCurrentWindow();
2022  if (window->SkipItems)
2023  return false;
2024 
2025  ImGuiContext& g = *GImGui;
2026  PushID(label);
2027  BeginGroup();
2029 
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);
2031  PopItemWidth();
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);
2034  PopItemWidth();
2036 
2037  TextUnformatted(label, FindRenderedTextEnd(label));
2038  EndGroup();
2039  PopID();
2040 
2041  return value_changed;
2042 }
2043 
2044 //-------------------------------------------------------------------------
2045 // [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc.
2046 //-------------------------------------------------------------------------
2047 // - SliderBehaviorT<>() [Internal]
2048 // - SliderBehavior() [Internal]
2049 // - SliderScalar()
2050 // - SliderScalarN()
2051 // - SliderFloat()
2052 // - SliderFloat2()
2053 // - SliderFloat3()
2054 // - SliderFloat4()
2055 // - SliderAngle()
2056 // - SliderInt()
2057 // - SliderInt2()
2058 // - SliderInt3()
2059 // - SliderInt4()
2060 // - VSliderScalar()
2061 // - VSliderFloat()
2062 // - VSliderInt()
2063 //-------------------------------------------------------------------------
2064 
2065 template<typename TYPE, typename FLOATTYPE>
2066 float ImGui::SliderCalcRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, float power, float linear_zero_pos)
2067 {
2068  if (v_min == v_max)
2069  return 0.0f;
2070 
2071  const bool is_power = (power != 1.0f) && (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double);
2072  const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min);
2073  if (is_power)
2074  {
2075  if (v_clamped < 0.0f)
2076  {
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;
2079  }
2080  else
2081  {
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);
2084  }
2085  }
2086 
2087  // Linear slider
2088  return (float)((FLOATTYPE)(v_clamped - v_min) / (FLOATTYPE)(v_max - v_min));
2089 }
2090 
2091 // FIXME: Move some of the code into SliderBehavior(). Current responsability is larger than what the equivalent DragBehaviorT<> does, we also do some rendering, etc.
2092 template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
2093 bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb)
2094 {
2095  ImGuiContext& g = *GImGui;
2096  const ImGuiStyle& style = g.Style;
2097 
2098  const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
2099  const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
2100  const bool is_power = (power != 1.0f) && is_decimal;
2101 
2102  const float grab_padding = 2.0f;
2103  const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f;
2104  float grab_sz = style.GrabMinSize;
2105  SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
2106  if (!is_decimal && v_range >= 0) // v_range < 0 may happen on integer overflows
2107  grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit
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;
2112 
2113  // For power curve sliders that cross over sign boundary we want the curve to be symmetric around 0.0f
2114  float linear_zero_pos; // 0.0->1.0f
2115  if (is_power && v_min * v_max < 0.0f)
2116  {
2117  // Different sign
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));
2121  }
2122  else
2123  {
2124  // Same sign
2125  linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f;
2126  }
2127 
2128  // Process interacting with the slider
2129  bool value_changed = false;
2130  if (g.ActiveId == id)
2131  {
2132  bool set_new_value = false;
2133  float clicked_t = 0.0f;
2135  {
2136  if (!g.IO.MouseDown[0])
2137  {
2138  ClearActiveID();
2139  }
2140  else
2141  {
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;
2144  if (axis == ImGuiAxis_Y)
2145  clicked_t = 1.0f - clicked_t;
2146  set_new_value = true;
2147  }
2148  }
2149  else if (g.ActiveIdSource == ImGuiInputSource_Nav)
2150  {
2152  float delta = (axis == ImGuiAxis_X) ? delta2.x : -delta2.y;
2154  {
2155  ClearActiveID();
2156  }
2157  else if (delta != 0.0f)
2158  {
2159  clicked_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
2160  const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
2161  if ((decimal_precision > 0) || is_power)
2162  {
2163  delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds
2165  delta /= 10.0f;
2166  }
2167  else
2168  {
2169  if ((v_range >= -100.0f && v_range <= 100.0f) || IsNavInputDown(ImGuiNavInput_TweakSlow))
2170  delta = ((delta < 0.0f) ? -1.0f : +1.0f) / (float)v_range; // Gamepad/keyboard tweak speeds in integer steps
2171  else
2172  delta /= 100.0f;
2173  }
2175  delta *= 10.0f;
2176  set_new_value = true;
2177  if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits
2178  set_new_value = false;
2179  else
2180  clicked_t = ImSaturate(clicked_t + delta);
2181  }
2182  }
2183 
2184  if (set_new_value)
2185  {
2186  TYPE v_new;
2187  if (is_power)
2188  {
2189  // Account for power curve scale on both sides of the zero
2190  if (clicked_t < linear_zero_pos)
2191  {
2192  // Negative: rescale to the negative range before powering
2193  float a = 1.0f - (clicked_t / linear_zero_pos);
2194  a = ImPow(a, power);
2195  v_new = ImLerp(ImMin(v_max, (TYPE)0), v_min, a);
2196  }
2197  else
2198  {
2199  // Positive: rescale to the positive range before powering
2200  float a;
2201  if (ImFabs(linear_zero_pos - 1.0f) > 1.e-6f)
2202  a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos);
2203  else
2204  a = clicked_t;
2205  a = ImPow(a, power);
2206  v_new = ImLerp(ImMax(v_min, (TYPE)0), v_max, a);
2207  }
2208  }
2209  else
2210  {
2211  // Linear slider
2212  if (is_decimal)
2213  {
2214  v_new = ImLerp(v_min, v_max, clicked_t);
2215  }
2216  else
2217  {
2218  // For integer values we want the clicking position to match the grab box so we round above
2219  // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property..
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;
2225  else
2226  v_new = v_min + v_new_off_floor;
2227  }
2228  }
2229 
2230  // Round to user desired precision based on format string
2231  v_new = RoundScalarWithFormatT<TYPE,SIGNEDTYPE>(format, data_type, v_new);
2232 
2233  // Apply result
2234  if (*v != v_new)
2235  {
2236  *v = v_new;
2237  value_changed = true;
2238  }
2239  }
2240  }
2241 
2242  // Output grab position so it can be displayed by the caller
2243  float grab_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
2244  if (axis == ImGuiAxis_Y)
2245  grab_t = 1.0f - grab_t;
2246  const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
2247  if (axis == ImGuiAxis_X)
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);
2249  else
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);
2251 
2252  return value_changed;
2253 }
2254 
2255 // For 32-bits and larger types, slider bounds are limited to half the natural type range.
2256 // So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok.
2257 // It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders.
2258 bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb)
2259 {
2260  switch (data_type)
2261  {
2262  case ImGuiDataType_S32:
2263  IM_ASSERT(*(const ImS32*)v_min >= IM_S32_MIN/2 && *(const ImS32*)v_max <= IM_S32_MAX/2);
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);
2265  case ImGuiDataType_U32:
2266  IM_ASSERT(*(const ImU32*)v_min <= IM_U32_MAX/2);
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);
2268  case ImGuiDataType_S64:
2269  IM_ASSERT(*(const ImS64*)v_min >= IM_S64_MIN/2 && *(const ImS64*)v_max <= IM_S64_MAX/2);
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);
2271  case ImGuiDataType_U64:
2272  IM_ASSERT(*(const ImU64*)v_min <= IM_U64_MAX/2);
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);
2274  case ImGuiDataType_Float:
2275  IM_ASSERT(*(const float*)v_min >= -FLT_MAX/2.0f && *(const float*)v_max <= FLT_MAX/2.0f);
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);
2277  case ImGuiDataType_Double:
2278  IM_ASSERT(*(const double*)v_min >= -DBL_MAX/2.0f && *(const double*)v_max <= DBL_MAX/2.0f);
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);
2280  case ImGuiDataType_COUNT: break;
2281  }
2282  IM_ASSERT(0);
2283  return false;
2284 }
2285 
2286 bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power)
2287 {
2288  ImGuiWindow* window = GetCurrentWindow();
2289  if (window->SkipItems)
2290  return false;
2291 
2292  ImGuiContext& g = *GImGui;
2293  const ImGuiStyle& style = g.Style;
2294  const ImGuiID id = window->GetID(label);
2295  const float w = CalcItemWidth();
2296 
2297  const ImVec2 label_size = CalcTextSize(label, NULL, true);
2298  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
2299  const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
2300 
2301  // NB- we don't call ItemSize() yet because we may turn into a text edit box below
2302  if (!ItemAdd(total_bb, id, &frame_bb))
2303  {
2304  ItemSize(total_bb, style.FramePadding.y);
2305  return false;
2306  }
2307 
2308  // Default format string when passing NULL
2309  // Patch old "%.0f" format string to use "%d", read function comments for more details.
2310  IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
2311  if (format == NULL)
2312  format = GDataTypeInfo[data_type].PrintFmt;
2313  else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0)
2314  format = PatchFormatStringFloatToInt(format);
2315 
2316  // Tabbing or CTRL-clicking on Slider turns it into an input box
2317  bool start_text_input = false;
2318  const bool tab_focus_requested = FocusableItemRegister(window, id);
2319  const bool hovered = ItemHoverable(frame_bb, id);
2320  if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
2321  {
2322  SetActiveID(id, window);
2323  SetFocusID(id, window);
2324  FocusWindow(window);
2326  if (tab_focus_requested || g.IO.KeyCtrl || g.NavInputId == id)
2327  {
2328  start_text_input = true;
2329  g.ScalarAsInputTextId = 0;
2330  }
2331  }
2332  if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
2333  {
2334  FocusableItemUnregister(window);
2335  return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format);
2336  }
2337 
2338  ItemSize(total_bb, style.FramePadding.y);
2339 
2340  // Draw frame
2342  RenderNavHighlight(frame_bb, id);
2343  RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
2344 
2345  // Slider behavior
2346  ImRect grab_bb;
2347  const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_None, &grab_bb);
2348  if (value_changed)
2349  MarkItemEdited(id);
2350 
2351  // Render grab
2353 
2354  // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
2355  char value_buf[64];
2356  const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format);
2357  RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f));
2358 
2359  if (label_size.x > 0.0f)
2360  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
2361 
2362  return value_changed;
2363 }
2364 
2365 // Add multiple sliders on 1 line for compact edition of multiple components
2366 bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, float power)
2367 {
2368  ImGuiWindow* window = GetCurrentWindow();
2369  if (window->SkipItems)
2370  return false;
2371 
2372  ImGuiContext& g = *GImGui;
2373  bool value_changed = false;
2374  BeginGroup();
2375  PushID(label);
2376  PushMultiItemsWidths(components);
2377  size_t type_size = GDataTypeInfo[data_type].Size;
2378  for (int i = 0; i < components; i++)
2379  {
2380  PushID(i);
2381  value_changed |= SliderScalar("##v", data_type, v, v_min, v_max, format, power);
2383  PopID();
2384  PopItemWidth();
2385  v = (void*)((char*)v + type_size);
2386  }
2387  PopID();
2388 
2389  TextUnformatted(label, FindRenderedTextEnd(label));
2390  EndGroup();
2391  return value_changed;
2392 }
2393 
2394 bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power)
2395 {
2396  return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power);
2397 }
2398 
2399 bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power)
2400 {
2401  return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power);
2402 }
2403 
2404 bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power)
2405 {
2406  return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power);
2407 }
2408 
2409 bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power)
2410 {
2411  return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power);
2412 }
2413 
2414 bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format)
2415 {
2416  if (format == NULL)
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.0f);
2420  *v_rad = v_deg * (2*IM_PI) / 360.0f;
2421  return value_changed;
2422 }
2423 
2424 bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format)
2425 {
2426  return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format);
2427 }
2428 
2429 bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format)
2430 {
2431  return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format);
2432 }
2433 
2434 bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format)
2435 {
2436  return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format);
2437 }
2438 
2439 bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format)
2440 {
2441  return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format);
2442 }
2443 
2444 bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power)
2445 {
2446  ImGuiWindow* window = GetCurrentWindow();
2447  if (window->SkipItems)
2448  return false;
2449 
2450  ImGuiContext& g = *GImGui;
2451  const ImGuiStyle& style = g.Style;
2452  const ImGuiID id = window->GetID(label);
2453 
2454  const ImVec2 label_size = CalcTextSize(label, NULL, true);
2455  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
2456  const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
2457 
2458  ItemSize(bb, style.FramePadding.y);
2459  if (!ItemAdd(frame_bb, id))
2460  return false;
2461 
2462  // Default format string when passing NULL
2463  // Patch old "%.0f" format string to use "%d", read function comments for more details.
2464  IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
2465  if (format == NULL)
2466  format = GDataTypeInfo[data_type].PrintFmt;
2467  else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0)
2468  format = PatchFormatStringFloatToInt(format);
2469 
2470  const bool hovered = ItemHoverable(frame_bb, id);
2471  if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id)
2472  {
2473  SetActiveID(id, window);
2474  SetFocusID(id, window);
2475  FocusWindow(window);
2477  }
2478 
2479  // Draw frame
2481  RenderNavHighlight(frame_bb, id);
2482  RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
2483 
2484  // Slider behavior
2485  ImRect grab_bb;
2486  const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical, &grab_bb);
2487  if (value_changed)
2488  MarkItemEdited(id);
2489 
2490  // Render grab
2492 
2493  // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
2494  // For the vertical slider we allow centered text to overlap the frame padding
2495  char value_buf[64];
2496  const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format);
2497  RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f));
2498  if (label_size.x > 0.0f)
2499  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
2500 
2501  return value_changed;
2502 }
2503 
2504 bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, float power)
2505 {
2506  return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, power);
2507 }
2508 
2509 bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format)
2510 {
2511  return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format);
2512 }
2513 
2514 //-------------------------------------------------------------------------
2515 // [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc.
2516 //-------------------------------------------------------------------------
2517 // - ImParseFormatFindStart() [Internal]
2518 // - ImParseFormatFindEnd() [Internal]
2519 // - ImParseFormatTrimDecorations() [Internal]
2520 // - ImParseFormatPrecision() [Internal]
2521 // - InputScalarAsWidgetReplacement() [Internal]
2522 // - InputScalar()
2523 // - InputScalarN()
2524 // - InputFloat()
2525 // - InputFloat2()
2526 // - InputFloat3()
2527 // - InputFloat4()
2528 // - InputInt()
2529 // - InputInt2()
2530 // - InputInt3()
2531 // - InputInt4()
2532 // - InputDouble()
2533 //-------------------------------------------------------------------------
2534 
2535 // We don't use strchr() because our strings are usually very short and often start with '%'
2536 const char* ImParseFormatFindStart(const char* fmt)
2537 {
2538  while (char c = fmt[0])
2539  {
2540  if (c == '%' && fmt[1] != '%')
2541  return fmt;
2542  else if (c == '%')
2543  fmt++;
2544  fmt++;
2545  }
2546  return fmt;
2547 }
2548 
2549 const char* ImParseFormatFindEnd(const char* fmt)
2550 {
2551  // Printf/scanf types modifiers: I/L/h/j/l/t/w/z. Other uppercase letters qualify as types aka end of the format.
2552  if (fmt[0] != '%')
2553  return fmt;
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++)
2557  {
2558  if (c >= 'A' && c <= 'Z' && ((1 << (c - 'A')) & ignored_uppercase_mask) == 0)
2559  return fmt + 1;
2560  if (c >= 'a' && c <= 'z' && ((1 << (c - 'a')) & ignored_lowercase_mask) == 0)
2561  return fmt + 1;
2562  }
2563  return fmt;
2564 }
2565 
2566 // Extract the format out of a format string with leading or trailing decorations
2567 // fmt = "blah blah" -> return fmt
2568 // fmt = "%.3f" -> return fmt
2569 // fmt = "hello %.3f" -> return fmt + 6
2570 // fmt = "%.3f hello" -> return buf written with "%.3f"
2571 const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, int buf_size)
2572 {
2573  const char* fmt_start = ImParseFormatFindStart(fmt);
2574  if (fmt_start[0] != '%')
2575  return fmt;
2576  const char* fmt_end = ImParseFormatFindEnd(fmt_start);
2577  if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data.
2578  return fmt_start;
2579  ImStrncpy(buf, fmt_start, ImMin((int)(fmt_end + 1 - fmt_start), buf_size));
2580  return buf;
2581 }
2582 
2583 // Parse display precision back from the display format string
2584 // FIXME: This is still used by some navigation code path to infer a minimum tweak step, but we should aim to rework widgets so it isn't needed.
2585 int ImParseFormatPrecision(const char* fmt, int default_precision)
2586 {
2587  fmt = ImParseFormatFindStart(fmt);
2588  if (fmt[0] != '%')
2589  return default_precision;
2590  fmt++;
2591  while (*fmt >= '0' && *fmt <= '9')
2592  fmt++;
2593  int precision = INT_MAX;
2594  if (*fmt == '.')
2595  {
2596  fmt = ImAtoi<int>(fmt + 1, &precision);
2597  if (precision < 0 || precision > 99)
2598  precision = default_precision;
2599  }
2600  if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation
2601  precision = -1;
2602  if ((*fmt == 'g' || *fmt == 'G') && precision == INT_MAX)
2603  precision = -1;
2604  return (precision == INT_MAX) ? default_precision : precision;
2605 }
2606 
2607 // Create text input in place of an active drag/slider (used when doing a CTRL+Click on drag/slider widgets)
2608 // FIXME: Logic is awkward and confusing. This should be reworked to facilitate using in other situations.
2609 bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format)
2610 {
2611  ImGuiContext& g = *GImGui;
2612  ImGuiWindow* window = GetCurrentWindow();
2613 
2614  // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen)
2615  // On the first frame, g.ScalarAsInputTextId == 0, then on subsequent frames it becomes == id
2616  SetActiveID(g.ScalarAsInputTextId, window);
2617  SetHoveredID(0);
2619 
2620  char fmt_buf[32];
2621  char data_buf[32];
2622  format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
2623  DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format);
2624  ImStrTrimBlanks(data_buf);
2626  bool value_changed = InputTextEx(label, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags);
2627  if (g.ScalarAsInputTextId == 0) // First frame we started displaying the InputText widget
2628  {
2629  IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID
2631  SetHoveredID(id);
2632  }
2633  if (value_changed)
2634  return DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialText.Data, data_type, data_ptr, NULL);
2635  return false;
2636 }
2637 
2638 bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_ptr, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags)
2639 {
2640  ImGuiWindow* window = GetCurrentWindow();
2641  if (window->SkipItems)
2642  return false;
2643 
2644  ImGuiContext& g = *GImGui;
2645  const ImGuiStyle& style = g.Style;
2646 
2647  IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
2648  if (format == NULL)
2649  format = GDataTypeInfo[data_type].PrintFmt;
2650 
2651  char buf[64];
2652  DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, format);
2653 
2654  bool value_changed = false;
2658 
2659  if (step != NULL)
2660  {
2661  const float button_size = GetFrameHeight();
2662 
2663  BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
2664  PushID(label);
2665  PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
2666  if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
2667  value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, format);
2668  PopItemWidth();
2669 
2670  // Step buttons
2672  if (flags & ImGuiInputTextFlags_ReadOnly)
2673  button_flags |= ImGuiButtonFlags_Disabled;
2674  SameLine(0, style.ItemInnerSpacing.x);
2675  if (ButtonEx("-", ImVec2(button_size, button_size), button_flags))
2676  {
2677  DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step);
2678  value_changed = true;
2679  }
2680  SameLine(0, style.ItemInnerSpacing.x);
2681  if (ButtonEx("+", ImVec2(button_size, button_size), button_flags))
2682  {
2683  DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step);
2684  value_changed = true;
2685  }
2686  SameLine(0, style.ItemInnerSpacing.x);
2687  TextUnformatted(label, FindRenderedTextEnd(label));
2688 
2689  PopID();
2690  EndGroup();
2691  }
2692  else
2693  {
2694  if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
2695  value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, format);
2696  }
2697 
2698  return value_changed;
2699 }
2700 
2701 bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags)
2702 {
2703  ImGuiWindow* window = GetCurrentWindow();
2704  if (window->SkipItems)
2705  return false;
2706 
2707  ImGuiContext& g = *GImGui;
2708  bool value_changed = false;
2709  BeginGroup();
2710  PushID(label);
2711  PushMultiItemsWidths(components);
2712  size_t type_size = GDataTypeInfo[data_type].Size;
2713  for (int i = 0; i < components; i++)
2714  {
2715  PushID(i);
2716  value_changed |= InputScalar("##v", data_type, v, step, step_fast, format, flags);
2718  PopID();
2719  PopItemWidth();
2720  v = (void*)((char*)v + type_size);
2721  }
2722  PopID();
2723 
2724  TextUnformatted(label, FindRenderedTextEnd(label));
2725  EndGroup();
2726  return value_changed;
2727 }
2728 
2729 bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags)
2730 {
2732  return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, flags);
2733 }
2734 
2735 bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags)
2736 {
2737  return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags);
2738 }
2739 
2740 bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags flags)
2741 {
2742  return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags);
2743 }
2744 
2745 bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags flags)
2746 {
2747  return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags);
2748 }
2749 
2750 // Prefer using "const char* format" directly, which is more flexible and consistent with other API.
2751 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
2752 bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags flags)
2753 {
2754  char format[16] = "%f";
2755  if (decimal_precision >= 0)
2756  ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
2757  return InputFloat(label, v, step, step_fast, format, flags);
2758 }
2759 
2760 bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags flags)
2761 {
2762  char format[16] = "%f";
2763  if (decimal_precision >= 0)
2764  ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
2765  return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags);
2766 }
2767 
2768 bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags flags)
2769 {
2770  char format[16] = "%f";
2771  if (decimal_precision >= 0)
2772  ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
2773  return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags);
2774 }
2775 
2776 bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags flags)
2777 {
2778  char format[16] = "%f";
2779  if (decimal_precision >= 0)
2780  ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
2781  return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags);
2782 }
2783 #endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
2784 
2785 bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags flags)
2786 {
2787  // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes.
2788  const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d";
2789  return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, flags);
2790 }
2791 
2792 bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags)
2793 {
2794  return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", flags);
2795 }
2796 
2797 bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags)
2798 {
2799  return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", flags);
2800 }
2801 
2802 bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags)
2803 {
2804  return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags);
2805 }
2806 
2807 bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags)
2808 {
2810  return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), format, flags);
2811 }
2812 
2813 //-------------------------------------------------------------------------
2814 // [SECTION] Widgets: InputText, InputTextMultiline
2815 //-------------------------------------------------------------------------
2816 // - InputText()
2817 // - InputTextMultiline()
2818 // - InputTextEx() [Internal]
2819 //-------------------------------------------------------------------------
2820 
2821 bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
2822 {
2823  IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
2824  return InputTextEx(label, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data);
2825 }
2826 
2827 bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
2828 {
2829  return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);
2830 }
2831 
2832 static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
2833 {
2834  int line_count = 0;
2835  const char* s = text_begin;
2836  while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding
2837  if (c == '\n')
2838  line_count++;
2839  s--;
2840  if (s[0] != '\n' && s[0] != '\r')
2841  line_count++;
2842  *out_text_end = s;
2843  return line_count;
2844 }
2845 
2846 static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line)
2847 {
2848  ImFont* font = GImGui->Font;
2849  const float line_height = GImGui->FontSize;
2850  const float scale = line_height / font->FontSize;
2851 
2852  ImVec2 text_size = ImVec2(0,0);
2853  float line_width = 0.0f;
2854 
2855  const ImWchar* s = text_begin;
2856  while (s < text_end)
2857  {
2858  unsigned int c = (unsigned int)(*s++);
2859  if (c == '\n')
2860  {
2861  text_size.x = ImMax(text_size.x, line_width);
2862  text_size.y += line_height;
2863  line_width = 0.0f;
2864  if (stop_on_new_line)
2865  break;
2866  continue;
2867  }
2868  if (c == '\r')
2869  continue;
2870 
2871  const float char_width = font->GetCharAdvance((ImWchar)c) * scale;
2872  line_width += char_width;
2873  }
2874 
2875  if (text_size.x < line_width)
2876  text_size.x = line_width;
2877 
2878  if (out_offset)
2879  *out_offset = ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n
2880 
2881  if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n
2882  text_size.y += line_height;
2883 
2884  if (remaining)
2885  *remaining = s;
2886 
2887  return text_size;
2888 }
2889 
2890 // Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar)
2891 namespace ImGuiStb
2892 {
2893 
2894 static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; }
2895 static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->TextW[idx]; }
2896 static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx+char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; return GImGui->Font->GetCharAdvance(c) * (GImGui->FontSize / GImGui->Font->FontSize); }
2897 static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : key; }
2899 static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx)
2900 {
2901  const ImWchar* text = obj->TextW.Data;
2902  const ImWchar* text_remaining = NULL;
2903  const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true);
2904  r->x0 = 0.0f;
2905  r->x1 = size.x;
2906  r->baseline_y_delta = size.y;
2907  r->ymin = 0.0f;
2908  r->ymax = size.y;
2909  r->num_chars = (int)(text_remaining - (text + line_start_idx));
2910 }
2911 
2912 static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
2913 static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->TextW[idx-1] ) && !is_separator( obj->TextW[idx] ) ) : 1; }
2914 static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
2915 #ifdef __APPLE__ // FIXME: Move setting to IO structure
2916 static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->TextW[idx-1] ) && is_separator( obj->TextW[idx] ) ) : 1; }
2917 static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
2918 #else
2919 static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
2920 #endif
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
2923 
2924 static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)
2925 {
2926  ImWchar* dst = obj->TextW.Data + pos;
2927 
2928  // We maintain our buffer length in both UTF-8 and wchar formats
2929  obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);
2930  obj->CurLenW -= n;
2931 
2932  // Offset remaining text (FIXME-OPT: Use memmove)
2933  const ImWchar* src = obj->TextW.Data + pos + n;
2934  while (ImWchar c = *src++)
2935  *dst++ = c;
2936  *dst = '\0';
2937 }
2938 
2939 static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len)
2940 {
2941  const bool is_resizable = (obj->UserFlags & ImGuiInputTextFlags_CallbackResize) != 0;
2942  const int text_len = obj->CurLenW;
2943  IM_ASSERT(pos <= text_len);
2944 
2945  const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
2946  if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA))
2947  return false;
2948 
2949  // Grow internal buffer if needed
2950  if (new_text_len + text_len + 1 > obj->TextW.Size)
2951  {
2952  if (!is_resizable)
2953  return false;
2954  IM_ASSERT(text_len < obj->TextW.Size);
2955  obj->TextW.resize(text_len + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1);
2956  }
2957 
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));
2962 
2963  obj->CurLenW += new_text_len;
2964  obj->CurLenA += new_text_len_utf8;
2965  obj->TextW[obj->CurLenW] = '\0';
2966 
2967  return true;
2968 }
2969 
2970 // We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols)
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
2986 
2987 #define STB_TEXTEDIT_IMPLEMENTATION
2988 #include "imstb_textedit.h"
2989 
2990 }
2991 
2993 {
2994  stb_textedit_key(this, &StbState, key);
2995  CursorFollow = true;
2996  CursorAnimReset();
2997 }
2998 
3000 {
3001  memset(this, 0, sizeof(*this));
3002 }
3003 
3004 // Public API to manipulate UTF-8 text
3005 // We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
3006 // FIXME: The existence of this rarely exercised code path is a bit of a nuisance.
3007 void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count)
3008 {
3009  IM_ASSERT(pos + bytes_count <= BufTextLen);
3010  char* dst = Buf + pos;
3011  const char* src = Buf + pos + bytes_count;
3012  while (char c = *src++)
3013  *dst++ = c;
3014  *dst = '\0';
3015 
3016  if (CursorPos + bytes_count >= pos)
3017  CursorPos -= bytes_count;
3018  else if (CursorPos >= pos)
3019  CursorPos = pos;
3021  BufDirty = true;
3022  BufTextLen -= bytes_count;
3023 }
3024 
3025 void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end)
3026 {
3027  const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
3028  const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
3029  if (new_text_len + BufTextLen >= BufSize)
3030  {
3031  if (!is_resizable)
3032  return;
3033 
3034  // Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the midly similar code (until we remove the U16 buffer alltogether!)
3035  ImGuiContext& g = *GImGui;
3036  ImGuiInputTextState* edit_state = &g.InputTextState;
3037  IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
3038  IM_ASSERT(Buf == edit_state->TempBuffer.Data);
3039  int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
3040  edit_state->TempBuffer.reserve(new_buf_size + 1);
3041  Buf = edit_state->TempBuffer.Data;
3042  BufSize = edit_state->BufCapacityA = new_buf_size;
3043  }
3044 
3045  if (BufTextLen != pos)
3046  memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos));
3047  memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
3048  Buf[BufTextLen + new_text_len] = '\0';
3049 
3050  if (CursorPos >= pos)
3051  CursorPos += new_text_len;
3053  BufDirty = true;
3054  BufTextLen += new_text_len;
3055 }
3056 
3057 // Return false to discard a character.
3058 static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
3059 {
3060  unsigned int c = *p_char;
3061 
3062  if (c < 128 && c != ' ' && !isprint((int)(c & 0xFF)))
3063  {
3064  bool pass = false;
3065  pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline));
3066  pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput));
3067  if (!pass)
3068  return false;
3069  }
3070 
3071  if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX seems to send private characters for special keys like arrow keys.
3072  return false;
3073 
3075  {
3077  if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
3078  return false;
3079 
3081  if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E'))
3082  return false;
3083 
3085  if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))
3086  return false;
3087 
3089  if (c >= 'a' && c <= 'z')
3090  *p_char = (c += (unsigned int)('A'-'a'));
3091 
3093  if (ImCharIsBlankW(c))
3094  return false;
3095  }
3096 
3098  {
3099  ImGuiInputTextCallbackData callback_data;
3100  memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
3102  callback_data.EventChar = (ImWchar)c;
3103  callback_data.Flags = flags;
3104  callback_data.UserData = user_data;
3105  if (callback(&callback_data) != 0)
3106  return false;
3107  *p_char = callback_data.EventChar;
3108  if (!callback_data.EventChar)
3109  return false;
3110  }
3111 
3112  return true;
3113 }
3114 
3115 // Edit a string of text
3116 // - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!".
3117 // This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
3118 // Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator.
3119 // - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect.
3120 // - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h
3121 // (FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188)
3122 bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data)
3123 {
3124  ImGuiWindow* window = GetCurrentWindow();
3125  if (window->SkipItems)
3126  return false;
3127 
3128  IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys)
3129  IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key)
3130 
3131  ImGuiContext& g = *GImGui;
3132  ImGuiIO& io = g.IO;
3133  const ImGuiStyle& style = g.Style;
3134 
3135  const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
3136  const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0;
3137  const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
3138  const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
3139  const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
3140  if (is_resizable)
3141  IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
3142 
3143  if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope,
3144  BeginGroup();
3145  const ImGuiID id = window->GetID(label);
3146  const ImVec2 label_size = CalcTextSize(label, NULL, true);
3147  ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line
3148  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
3149  const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
3150 
3151  ImGuiWindow* draw_window = window;
3152  if (is_multiline)
3153  {
3154  ItemAdd(total_bb, id, &frame_bb);
3155  if (!BeginChildFrame(id, frame_bb.GetSize()))
3156  {
3157  EndChildFrame();
3158  EndGroup();
3159  return false;
3160  }
3161  draw_window = GetCurrentWindow();
3162  draw_window->DC.NavLayerActiveMaskNext |= draw_window->DC.NavLayerCurrentMask; // This is to ensure that EndChild() will display a navigation highlight
3163  size.x -= draw_window->ScrollbarSizes.x;
3164  }
3165  else
3166  {
3167  ItemSize(total_bb, style.FramePadding.y);
3168  if (!ItemAdd(total_bb, id, &frame_bb))
3169  return false;
3170  }
3171  const bool hovered = ItemHoverable(frame_bb, id);
3172  if (hovered)
3174 
3175  // Password pushes a temporary font with only a fallback glyph
3176  if (is_password)
3177  {
3178  const ImFontGlyph* glyph = g.Font->FindGlyph('*');
3179  ImFont* password_font = &g.InputTextPasswordFont;
3180  password_font->FontSize = g.Font->FontSize;
3181  password_font->Scale = g.Font->Scale;
3182  password_font->DisplayOffset = g.Font->DisplayOffset;
3183  password_font->Ascent = g.Font->Ascent;
3184  password_font->Descent = g.Font->Descent;
3185  password_font->ContainerAtlas = g.Font->ContainerAtlas;
3186  password_font->FallbackGlyph = glyph;
3187  password_font->FallbackAdvanceX = glyph->AdvanceX;
3188  IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty());
3189  PushFont(password_font);
3190  }
3191 
3192  // NB: we are only allowed to access 'edit_state' if we are the active widget.
3193  ImGuiInputTextState& edit_state = g.InputTextState;
3194 
3195  const bool focus_requested = FocusableItemRegister(window, id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing
3196  const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent);
3197  const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
3198 
3199  const bool user_clicked = hovered && io.MouseClicked[0];
3200  const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.ID == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY");
3201  const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_NavKeyboard));
3202 
3203  bool clear_active_id = false;
3204 
3205  bool select_all = (g.ActiveId != id) && ((flags & ImGuiInputTextFlags_AutoSelectAll) != 0 || user_nav_input_start) && (!is_multiline);
3206  if (focus_requested || user_clicked || user_scrolled || user_nav_input_start)
3207  {
3208  if (g.ActiveId != id)
3209  {
3210  // Start edition
3211  // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
3212  // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
3213  const int prev_len_w = edit_state.CurLenW;
3214  const int init_buf_len = (int)strlen(buf);
3215  edit_state.TextW.resize(buf_size+1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
3216  edit_state.InitialText.resize(init_buf_len + 1); // UTF-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
3217  memcpy(edit_state.InitialText.Data, buf, init_buf_len + 1);
3218  const char* buf_end = NULL;
3219  edit_state.CurLenW = ImTextStrFromUtf8(edit_state.TextW.Data, buf_size, buf, NULL, &buf_end);
3220  edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImStrncpy() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
3221  edit_state.CursorAnimReset();
3222 
3223  // Preserve cursor position and undo/redo stack if we come back to same widget
3224  // FIXME: We should probably compare the whole buffer to be on the safety side. Comparing buf (utf8) and edit_state.Text (wchar).
3225  const bool recycle_state = (edit_state.ID == id) && (prev_len_w == edit_state.CurLenW);
3226  if (recycle_state)
3227  {
3228  // Recycle existing cursor/selection/undo stack but clamp position
3229  // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
3230  edit_state.CursorClamp();
3231  }
3232  else
3233  {
3234  edit_state.ID = id;
3235  edit_state.ScrollX = 0.0f;
3236  stb_textedit_initialize_state(&edit_state.StbState, !is_multiline);
3237  if (!is_multiline && focus_requested_by_code)
3238  select_all = true;
3239  }
3241  edit_state.StbState.insert_mode = true;
3242  if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl)))
3243  select_all = true;
3244  }
3245  SetActiveID(id, window);
3246  SetFocusID(id, window);
3247  FocusWindow(window);
3248  if (!is_multiline && !(flags & ImGuiInputTextFlags_CallbackHistory))
3249  g.ActiveIdAllowNavDirFlags |= ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down));
3250  }
3251  else if (io.MouseClicked[0])
3252  {
3253  // Release focus when we click outside
3254  clear_active_id = true;
3255  }
3256 
3257  bool value_changed = false;
3258  bool enter_pressed = false;
3259  int backup_current_text_length = 0;
3260 
3261  if (g.ActiveId == id)
3262  {
3263  if (!is_editable && !g.ActiveIdIsJustActivated)
3264  {
3265  // When read-only we always use the live data passed to the function
3266  edit_state.TextW.resize(buf_size+1);
3267  const char* buf_end = NULL;
3268  edit_state.CurLenW = ImTextStrFromUtf8(edit_state.TextW.Data, edit_state.TextW.Size, buf, NULL, &buf_end);
3269  edit_state.CurLenA = (int)(buf_end - buf);
3270  edit_state.CursorClamp();
3271  }
3272 
3273  backup_current_text_length = edit_state.CurLenA;
3274  edit_state.BufCapacityA = buf_size;
3275  edit_state.UserFlags = flags;
3276  edit_state.UserCallback = callback;
3277  edit_state.UserCallbackData = callback_user_data;
3278 
3279  // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
3280  // Down the line we should have a cleaner library-wide concept of Selected vs Active.
3281  g.ActiveIdAllowOverlap = !io.MouseDown[0];
3282  g.WantTextInputNextFrame = 1;
3283 
3284  // Edit in progress
3285  const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
3286  const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f));
3287 
3288  const bool is_osx = io.ConfigMacOSXBehaviors;
3289  if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0]))
3290  {
3291  edit_state.SelectAll();
3292  edit_state.SelectedAllMouseLock = true;
3293  }
3294  else if (hovered && is_osx && io.MouseDoubleClicked[0])
3295  {
3296  // Double-click select a word only, OS X style (by simulating keystrokes)
3299  }
3300  else if (io.MouseClicked[0] && !edit_state.SelectedAllMouseLock)
3301  {
3302  if (hovered)
3303  {
3304  stb_textedit_click(&edit_state, &edit_state.StbState, mouse_x, mouse_y);
3305  edit_state.CursorAnimReset();
3306  }
3307  }
3308  else if (io.MouseDown[0] && !edit_state.SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f))
3309  {
3310  stb_textedit_drag(&edit_state, &edit_state.StbState, mouse_x, mouse_y);
3311  edit_state.CursorAnimReset();
3312  edit_state.CursorFollow = true;
3313  }
3314  if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])
3315  edit_state.SelectedAllMouseLock = false;
3316 
3317  if (io.InputQueueCharacters.Size > 0)
3318  {
3319  // Process text input (before we check for Return because using some IME will effectively send a Return?)
3320  // We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters.
3321  bool ignore_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper);
3322  if (!ignore_inputs && is_editable && !user_nav_input_start)
3323  for (int n = 0; n < io.InputQueueCharacters.Size; n++)
3324  {
3325  // Insert character if they pass filtering
3326  unsigned int c = (unsigned int)io.InputQueueCharacters[n];
3327  if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
3328  edit_state.OnKeyPressed((int)c);
3329  }
3330 
3331  // Consume characters
3333  }
3334  }
3335 
3336  bool cancel_edit = false;
3337  if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id)
3338  {
3339  // Handle key-presses
3340  const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
3341  const bool is_osx = io.ConfigMacOSXBehaviors;
3342  const bool is_shortcut_key = (is_osx ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl
3343  const bool is_osx_shift_shortcut = is_osx && io.KeySuper && io.KeyShift && !io.KeyCtrl && !io.KeyAlt;
3344  const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
3345  const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End
3346  const bool is_ctrl_key_only = io.KeyCtrl && !io.KeyShift && !io.KeyAlt && !io.KeySuper;
3347  const bool is_shift_key_only = io.KeyShift && !io.KeyCtrl && !io.KeyAlt && !io.KeySuper;
3348 
3349  const bool is_cut = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Delete))) && is_editable && !is_password && (!is_multiline || edit_state.HasSelection());
3350  const bool is_copy = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_password && (!is_multiline || edit_state.HasSelection());
3351  const bool is_paste = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && is_editable;
3352  const bool is_undo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Z)) && is_editable && is_undoable);
3353  const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && is_editable && is_undoable;
3354 
3355  if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
3356  else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
3357  else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
3358  else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
3359  else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
3360  else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
3361  else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
3362  else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable)
3363  {
3364  if (!edit_state.HasSelection())
3365  {
3366  if (is_wordmove_key_down) edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT|STB_TEXTEDIT_K_SHIFT);
3367  else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) edit_state.OnKeyPressed(STB_TEXTEDIT_K_LINESTART|STB_TEXTEDIT_K_SHIFT);
3368  }
3369  edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
3370  }
3371  else if (IsKeyPressedMap(ImGuiKey_Enter))
3372  {
3373  bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
3374  if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl))
3375  {
3376  enter_pressed = clear_active_id = true;
3377  }
3378  else if (is_editable)
3379  {
3380  unsigned int c = '\n'; // Insert new line
3381  if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
3382  edit_state.OnKeyPressed((int)c);
3383  }
3384  }
3385  else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !io.KeyCtrl && !io.KeyShift && !io.KeyAlt && is_editable)
3386  {
3387  unsigned int c = '\t'; // Insert TAB
3388  if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
3389  edit_state.OnKeyPressed((int)c);
3390  }
3391  else if (IsKeyPressedMap(ImGuiKey_Escape))
3392  {
3393  clear_active_id = cancel_edit = true;
3394  }
3395  else if (is_undo || is_redo)
3396  {
3397  edit_state.OnKeyPressed(is_undo ? STB_TEXTEDIT_K_UNDO : STB_TEXTEDIT_K_REDO);
3398  edit_state.ClearSelection();
3399  }
3400  else if (is_shortcut_key && IsKeyPressedMap(ImGuiKey_A))
3401  {
3402  edit_state.SelectAll();
3403  edit_state.CursorFollow = true;
3404  }
3405  else if (is_cut || is_copy)
3406  {
3407  // Cut, Copy
3408  if (io.SetClipboardTextFn)
3409  {
3410  const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0;
3411  const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : edit_state.CurLenW;
3412  edit_state.TempBuffer.resize((ie-ib) * 4 + 1);
3413  ImTextStrToUtf8(edit_state.TempBuffer.Data, edit_state.TempBuffer.Size, edit_state.TextW.Data+ib, edit_state.TextW.Data+ie);
3414  SetClipboardText(edit_state.TempBuffer.Data);
3415  }
3416  if (is_cut)
3417  {
3418  if (!edit_state.HasSelection())
3419  edit_state.SelectAll();
3420  edit_state.CursorFollow = true;
3421  stb_textedit_cut(&edit_state, &edit_state.StbState);
3422  }
3423  }
3424  else if (is_paste)
3425  {
3426  if (const char* clipboard = GetClipboardText())
3427  {
3428  // Filter pasted buffer
3429  const int clipboard_len = (int)strlen(clipboard);
3430  ImWchar* clipboard_filtered = (ImWchar*)MemAlloc((clipboard_len+1) * sizeof(ImWchar));
3431  int clipboard_filtered_len = 0;
3432  for (const char* s = clipboard; *s; )
3433  {
3434  unsigned int c;
3435  s += ImTextCharFromUtf8(&c, s, NULL);
3436  if (c == 0)
3437  break;
3438  if (c >= 0x10000 || !InputTextFilterCharacter(&c, flags, callback, callback_user_data))
3439  continue;
3440  clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
3441  }
3442  clipboard_filtered[clipboard_filtered_len] = 0;
3443  if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation
3444  {
3445  stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len);
3446  edit_state.CursorFollow = true;
3447  }
3448  MemFree(clipboard_filtered);
3449  }
3450  }
3451  }
3452 
3453  if (g.ActiveId == id)
3454  {
3455  const char* apply_new_text = NULL;
3456  int apply_new_text_length = 0;
3457  if (cancel_edit)
3458  {
3459  // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
3460  if (is_editable && strcmp(buf, edit_state.InitialText.Data) != 0)
3461  {
3462  apply_new_text = edit_state.InitialText.Data;
3463  apply_new_text_length = edit_state.InitialText.Size - 1;
3464  }
3465  }
3466 
3467  // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame.
3468  // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. Also this allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage.
3469  bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
3470  if (apply_edit_back_to_user_buffer)
3471  {
3472  // Apply new value immediately - copy modified buffer back
3473  // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
3474  // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect.
3475  // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.
3476  if (is_editable)
3477  {
3478  edit_state.TempBuffer.resize(edit_state.TextW.Size * 4 + 1);
3479  ImTextStrToUtf8(edit_state.TempBuffer.Data, edit_state.TempBuffer.Size, edit_state.TextW.Data, NULL);
3480  }
3481 
3482  // User callback
3484  {
3485  IM_ASSERT(callback != NULL);
3486 
3487  // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
3488  ImGuiInputTextFlags event_flag = 0;
3489  ImGuiKey event_key = ImGuiKey_COUNT;
3491  {
3493  event_key = ImGuiKey_Tab;
3494  }
3496  {
3498  event_key = ImGuiKey_UpArrow;
3499  }
3501  {
3503  event_key = ImGuiKey_DownArrow;
3504  }
3505  else if (flags & ImGuiInputTextFlags_CallbackAlways)
3507 
3508  if (event_flag)
3509  {
3510  ImGuiInputTextCallbackData callback_data;
3511  memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
3512  callback_data.EventFlag = event_flag;
3513  callback_data.Flags = flags;
3514  callback_data.UserData = callback_user_data;
3515 
3516  callback_data.EventKey = event_key;
3517  callback_data.Buf = edit_state.TempBuffer.Data;
3518  callback_data.BufTextLen = edit_state.CurLenA;
3519  callback_data.BufSize = edit_state.BufCapacityA;
3520  callback_data.BufDirty = false;
3521 
3522  // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188)
3523  ImWchar* text = edit_state.TextW.Data;
3524  const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.cursor);
3525  const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_start);
3526  const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_end);
3527 
3528  // Call user code
3529  callback(&callback_data);
3530 
3531  // Read back what user may have modified
3532  IM_ASSERT(callback_data.Buf == edit_state.TempBuffer.Data); // Invalid to modify those fields
3533  IM_ASSERT(callback_data.BufSize == edit_state.BufCapacityA);
3534  IM_ASSERT(callback_data.Flags == flags);
3535  if (callback_data.CursorPos != utf8_cursor_pos) { edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); edit_state.CursorFollow = true; }
3536  if (callback_data.SelectionStart != utf8_selection_start) { edit_state.StbState.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); }
3537  if (callback_data.SelectionEnd != utf8_selection_end) { edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
3538  if (callback_data.BufDirty)
3539  {
3540  IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
3541  if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
3542  edit_state.TextW.resize(edit_state.TextW.Size + (callback_data.BufTextLen - backup_current_text_length));
3543  edit_state.CurLenW = ImTextStrFromUtf8(edit_state.TextW.Data, edit_state.TextW.Size, callback_data.Buf, NULL);
3544  edit_state.CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
3545  edit_state.CursorAnimReset();
3546  }
3547  }
3548  }
3549 
3550  // Will copy result string if modified
3551  if (is_editable && strcmp(edit_state.TempBuffer.Data, buf) != 0)
3552  {
3553  apply_new_text = edit_state.TempBuffer.Data;
3554  apply_new_text_length = edit_state.CurLenA;
3555  }
3556  }
3557 
3558  // Copy result to user buffer
3559  if (apply_new_text)
3560  {
3561  IM_ASSERT(apply_new_text_length >= 0);
3562  if (backup_current_text_length != apply_new_text_length && is_resizable)
3563  {
3564  ImGuiInputTextCallbackData callback_data;
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);
3576  }
3577 
3578  // If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
3579  ImStrncpy(buf, edit_state.TempBuffer.Data, ImMin(apply_new_text_length + 1, buf_size));
3580  value_changed = true;
3581  }
3582 
3583  // Clear temporary user storage
3584  edit_state.UserFlags = 0;
3585  edit_state.UserCallback = NULL;
3586  edit_state.UserCallbackData = NULL;
3587  }
3588 
3589  // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
3590  if (clear_active_id && g.ActiveId == id)
3591  ClearActiveID();
3592 
3593  // Render
3594  // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on.
3595  const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempBuffer.Data : buf; buf = NULL;
3596 
3597  // Set upper limit of single-line InputTextEx() at 2 million characters strings. The current pathological worst case is a long line
3598  // without any carriage return, which would makes ImFont::RenderText() reserve too many vertices and probably crash. Avoid it altogether.
3599  // Note that we only use this limit on single-line InputText(), so a pathologically large line on a InputTextMultiline() would still crash.
3600  const int buf_display_max_length = 2 * 1024 * 1024;
3601 
3602  if (!is_multiline)
3603  {
3604  RenderNavHighlight(frame_bb, id);
3605  RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
3606  }
3607 
3608  const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x, frame_bb.Min.y + size.y); // Not using frame_bb.Max because we have adjusted size
3609  ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding;
3610  ImVec2 text_size(0.f, 0.f);
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)
3613  {
3614  edit_state.CursorAnim += io.DeltaTime;
3615 
3616  // This is going to be messy. We need to:
3617  // - Display the text (this alone can be more easily clipped)
3618  // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation)
3619  // - Measure text height (for scrollbar)
3620  // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
3621  // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
3622  const ImWchar* text_begin = edit_state.TextW.Data;
3623  ImVec2 cursor_offset, select_start_offset;
3624 
3625  {
3626  // Count lines + find lines numbers straddling 'cursor' and 'select_start' position.
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 };
3632  if (edit_state.StbState.select_start != edit_state.StbState.select_end)
3633  {
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++;
3637  }
3638 
3639  // Iterate all lines to find our line numbers
3640  // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
3641  searches_remaining += is_multiline ? 1 : 0;
3642  int line_count = 0;
3643  //for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++) // FIXME-OPT: Could use this when wchar_t are 16-bits
3644  for (const ImWchar* s = text_begin; *s != 0; s++)
3645  if (*s == '\n')
3646  {
3647  line_count++;
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; }
3650  }
3651  line_count++;
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;
3654 
3655  // Calculate 2d position by finding the beginning of the line and measuring distance
3656  cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
3657  cursor_offset.y = searches_result_line_number[0] * g.FontSize;
3658  if (searches_result_line_number[1] >= 0)
3659  {
3660  select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
3661  select_start_offset.y = searches_result_line_number[1] * g.FontSize;
3662  }
3663 
3664  // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224)
3665  if (is_multiline)
3666  text_size = ImVec2(size.x, line_count * g.FontSize);
3667  }
3668 
3669  // Scroll
3670  if (edit_state.CursorFollow)
3671  {
3672  // Horizontal scroll in chunks of quarter width
3674  {
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.0f, 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);
3680  }
3681  else
3682  {
3683  edit_state.ScrollX = 0.0f;
3684  }
3685 
3686  // Vertical scroll
3687  if (is_multiline)
3688  {
3689  float scroll_y = draw_window->Scroll.y;
3690  if (cursor_offset.y - g.FontSize < scroll_y)
3691  scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize);
3692  else if (cursor_offset.y - size.y >= scroll_y)
3693  scroll_y = cursor_offset.y - size.y;
3694  draw_window->DC.CursorPos.y += (draw_window->Scroll.y - scroll_y); // To avoid a frame of lag
3695  draw_window->Scroll.y = scroll_y;
3696  render_pos.y = draw_window->DC.CursorPos.y;
3697  }
3698  }
3699  edit_state.CursorFollow = false;
3700  const ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f);
3701 
3702  // Draw selection
3703  if (edit_state.StbState.select_start != edit_state.StbState.select_end)
3704  {
3705  const ImWchar* text_selected_begin = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end);
3706  const ImWchar* text_selected_end = text_begin + ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end);
3707 
3708  float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection.
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; )
3713  {
3714  if (rect_pos.y > clip_rect.w + g.FontSize)
3715  break;
3716  if (rect_pos.y < clip_rect.y)
3717  {
3718  //p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p); // FIXME-OPT: Could use this when wchar_t are 16-bits
3719  //p = p ? p + 1 : text_selected_end;
3720  while (p < text_selected_end)
3721  if (*p++ == '\n')
3722  break;
3723  }
3724  else
3725  {
3726  ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true);
3727  if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
3728  ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn));
3729  rect.ClipWith(clip_rect);
3730  if (rect.Overlaps(clip_rect))
3731  draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
3732  }
3733  rect_pos.x = render_pos.x - render_scroll.x;
3734  rect_pos.y += g.FontSize;
3735  }
3736  }
3737 
3738  const int buf_display_len = edit_state.CurLenA;
3739  if (is_multiline || buf_display_len < buf_display_max_length)
3740  draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos - render_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display + buf_display_len, 0.0f, is_multiline ? NULL : &clip_rect);
3741 
3742  // Draw blinking cursor
3743  bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (g.InputTextState.CursorAnim <= 0.0f) || ImFmod(g.InputTextState.CursorAnim, 1.20f) <= 0.80f;
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))
3747  draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
3748 
3749  // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
3750  if (is_editable)
3751  g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize);
3752  }
3753  else
3754  {
3755  // Render text only
3756  const char* buf_end = NULL;
3757  if (is_multiline)
3758  text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_end) * g.FontSize); // We don't need width
3759  else
3760  buf_end = buf_display + strlen(buf_display);
3761  if (is_multiline || (buf_end - buf_display) < buf_display_max_length)
3762  draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos, GetColorU32(ImGuiCol_Text), buf_display, buf_end, 0.0f, is_multiline ? NULL : &clip_rect);
3763  }
3764 
3765  if (is_multiline)
3766  {
3767  Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line
3768  EndChildFrame();
3769  EndGroup();
3770  }
3771 
3772  if (is_password)
3773  PopFont();
3774 
3775  // Log as text
3776  if (g.LogEnabled && !is_password)
3777  LogRenderedText(&render_pos, buf_display, NULL);
3778 
3779  if (label_size.x > 0)
3780  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
3781 
3782  if (value_changed)
3783  MarkItemEdited(id);
3784 
3785  if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
3786  return enter_pressed;
3787  else
3788  return value_changed;
3789 }
3790 
3791 //-------------------------------------------------------------------------
3792 // [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc.
3793 //-------------------------------------------------------------------------
3794 // - ColorEdit3()
3795 // - ColorEdit4()
3796 // - ColorPicker3()
3797 // - RenderColorRectWithAlphaCheckerboard() [Internal]
3798 // - ColorPicker4()
3799 // - ColorButton()
3800 // - SetColorEditOptions()
3801 // - ColorTooltip() [Internal]
3802 // - ColorEditOptionsPopup() [Internal]
3803 // - ColorPickerOptionsPopup() [Internal]
3804 //-------------------------------------------------------------------------
3805 
3806 bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags)
3807 {
3808  return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha);
3809 }
3810 
3811 // Edit colors components (each component in 0.0f..1.0f range).
3812 // See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
3813 // With typical options: Left-click on colored square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item.
3814 bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags)
3815 {
3816  ImGuiWindow* window = GetCurrentWindow();
3817  if (window->SkipItems)
3818  return false;
3819 
3820  ImGuiContext& g = *GImGui;
3821  const ImGuiStyle& style = g.Style;
3822  const float square_sz = GetFrameHeight();
3823  const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
3824  const float w_items_all = CalcItemWidth() - w_extra;
3825  const char* label_display_end = FindRenderedTextEnd(label);
3826 
3827  BeginGroup();
3828  PushID(label);
3829 
3830  // If we're not showing any slider there's no point in doing any HSV conversions
3831  const ImGuiColorEditFlags flags_untouched = flags;
3832  if (flags & ImGuiColorEditFlags_NoInputs)
3834 
3835  // Context menu: display and modify options (before defaults are applied)
3836  if (!(flags & ImGuiColorEditFlags_NoOptions))
3837  ColorEditOptionsPopup(col, flags);
3838 
3839  // Read stored options
3840  if (!(flags & ImGuiColorEditFlags__InputsMask))
3842  if (!(flags & ImGuiColorEditFlags__DataTypeMask))
3844  if (!(flags & ImGuiColorEditFlags__PickerMask))
3847 
3848  const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0;
3849  const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0;
3850  const int components = alpha ? 4 : 3;
3851 
3852  // Convert to the formats we need
3853  float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f };
3854  if (flags & ImGuiColorEditFlags_HSV)
3855  ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
3857 
3858  bool value_changed = false;
3859  bool value_changed_as_float = false;
3860 
3861  if ((flags & (ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_HSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
3862  {
3863  // RGB/HSV 0..255 Sliders
3864  const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
3865  const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
3866 
3867  const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x);
3868  const char* ids[4] = { "##X", "##Y", "##Z", "##W" };
3869  const char* fmt_table_int[3][4] =
3870  {
3871  { "%3d", "%3d", "%3d", "%3d" }, // Short display
3872  { "R:%3d", "G:%3d", "B:%3d", "A:%3d" }, // Long display for RGBA
3873  { "H:%3d", "S:%3d", "V:%3d", "A:%3d" } // Long display for HSVA
3874  };
3875  const char* fmt_table_float[3][4] =
3876  {
3877  { "%0.3f", "%0.3f", "%0.3f", "%0.3f" }, // Short display
3878  { "R:%0.3f", "G:%0.3f", "B:%0.3f", "A:%0.3f" }, // Long display for RGBA
3879  { "H:%0.3f", "S:%0.3f", "V:%0.3f", "A:%0.3f" } // Long display for HSVA
3880  };
3881  const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_HSV) ? 2 : 1;
3882 
3883  PushItemWidth(w_item_one);
3884  for (int n = 0; n < components; n++)
3885  {
3886  if (n > 0)
3887  SameLine(0, style.ItemInnerSpacing.x);
3888  if (n + 1 == components)
3889  PushItemWidth(w_item_last);
3890  if (flags & ImGuiColorEditFlags_Float)
3891  value_changed = value_changed_as_float = value_changed | DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
3892  else
3893  value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);
3894  if (!(flags & ImGuiColorEditFlags_NoOptions))
3895  OpenPopupOnItemClick("context");
3896  }
3897  PopItemWidth();
3898  PopItemWidth();
3899  }
3900  else if ((flags & ImGuiColorEditFlags_HEX) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
3901  {
3902  // RGB Hexadecimal Input
3903  char buf[64];
3904  if (alpha)
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));
3906  else
3907  ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255));
3908  PushItemWidth(w_items_all);
3910  {
3911  value_changed = true;
3912  char* p = buf;
3913  while (*p == '#' || ImCharIsBlankA(*p))
3914  p++;
3915  i[0] = i[1] = i[2] = i[3] = 0;
3916  if (alpha)
3917  sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)
3918  else
3919  sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
3920  }
3921  if (!(flags & ImGuiColorEditFlags_NoOptions))
3922  OpenPopupOnItemClick("context");
3923  PopItemWidth();
3924  }
3925 
3926  ImGuiWindow* picker_active_window = NULL;
3927  if (!(flags & ImGuiColorEditFlags_NoSmallPreview))
3928  {
3929  if (!(flags & ImGuiColorEditFlags_NoInputs))
3930  SameLine(0, style.ItemInnerSpacing.x);
3931 
3932  const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f);
3933  if (ColorButton("##ColorButton", col_v4, flags))
3934  {
3935  if (!(flags & ImGuiColorEditFlags_NoPicker))
3936  {
3937  // Store current color and open a picker
3938  g.ColorPickerRef = col_v4;
3939  OpenPopup("picker");
3940  SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1,style.ItemSpacing.y));
3941  }
3942  }
3943  if (!(flags & ImGuiColorEditFlags_NoOptions))
3944  OpenPopupOnItemClick("context");
3945 
3946  if (BeginPopup("picker"))
3947  {
3948  picker_active_window = g.CurrentWindow;
3949  if (label != label_display_end)
3950  {
3951  TextUnformatted(label, label_display_end);
3952  Spacing();
3953  }
3955  ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__InputsMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
3956  PushItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
3957  value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
3958  PopItemWidth();
3959  EndPopup();
3960  }
3961  }
3962 
3963  if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel))
3964  {
3965  SameLine(0, style.ItemInnerSpacing.x);
3966  TextUnformatted(label, label_display_end);
3967  }
3968 
3969  // Convert back
3970  if (picker_active_window == NULL)
3971  {
3972  if (!value_changed_as_float)
3973  for (int n = 0; n < 4; n++)
3974  f[n] = i[n] / 255.0f;
3975  if (flags & ImGuiColorEditFlags_HSV)
3976  ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
3977  if (value_changed)
3978  {
3979  col[0] = f[0];
3980  col[1] = f[1];
3981  col[2] = f[2];
3982  if (alpha)
3983  col[3] = f[3];
3984  }
3985  }
3986 
3987  PopID();
3988  EndGroup();
3989 
3990  // Drag and Drop Target
3991  // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.
3993  {
3995  {
3996  memcpy((float*)col, payload->Data, sizeof(float) * 3);
3997  value_changed = true;
3998  }
4000  {
4001  memcpy((float*)col, payload->Data, sizeof(float) * components);
4002  value_changed = true;
4003  }
4005  }
4006 
4007  // When picker is being actively used, use its active id so IsItemActive() will function on ColorEdit4().
4008  if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window)
4009  window->DC.LastItemId = g.ActiveId;
4010 
4011  if (value_changed)
4012  MarkItemEdited(window->DC.LastItemId);
4013 
4014  return value_changed;
4015 }
4016 
4017 bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags)
4018 {
4019  float col4[4] = { col[0], col[1], col[2], 1.0f };
4020  if (!ColorPicker4(label, col4, flags | ImGuiColorEditFlags_NoAlpha))
4021  return false;
4022  col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2];
4023  return true;
4024 }
4025 
4026 static inline ImU32 ImAlphaBlendColor(ImU32 col_a, ImU32 col_b)
4027 {
4028  float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f;
4029  int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t);
4030  int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t);
4031  int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t);
4032  return IM_COL32(r, g, b, 0xFF);
4033 }
4034 
4035 // Helper for ColorPicker4()
4036 // NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that.
4037 // I spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding alltogether.
4038 void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags)
4039 {
4040  ImGuiWindow* window = GetCurrentWindow();
4041  if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)
4042  {
4043  ImU32 col_bg1 = GetColorU32(ImAlphaBlendColor(IM_COL32(204,204,204,255), col));
4044  ImU32 col_bg2 = GetColorU32(ImAlphaBlendColor(IM_COL32(128,128,128,255), col));
4045  window->DrawList->AddRectFilled(p_min, p_max, col_bg1, rounding, rounding_corners_flags);
4046 
4047  int yi = 0;
4048  for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++)
4049  {
4050  float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y);
4051  if (y2 <= y1)
4052  continue;
4053  for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f)
4054  {
4055  float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x);
4056  if (x2 <= x1)
4057  continue;
4058  int rounding_corners_flags_cell = 0;
4059  if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopRight; }
4060  if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotRight; }
4061  rounding_corners_flags_cell &= rounding_corners_flags;
4062  window->DrawList->AddRectFilled(ImVec2(x1,y1), ImVec2(x2,y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell);
4063  }
4064  }
4065  }
4066  else
4067  {
4068  window->DrawList->AddRectFilled(p_min, p_max, col, rounding, rounding_corners_flags);
4069  }
4070 }
4071 
4072 // Helper for ColorPicker4()
4073 static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w)
4074 {
4075  ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32_BLACK);
4076  ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32_WHITE);
4077  ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32_BLACK);
4078  ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32_WHITE);
4079 }
4080 
4081 // Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
4082 // FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..)
4083 bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)
4084 {
4085  ImGuiContext& g = *GImGui;
4086  ImGuiWindow* window = GetCurrentWindow();
4087  ImDrawList* draw_list = window->DrawList;
4088 
4089  ImGuiStyle& style = g.Style;
4090  ImGuiIO& io = g.IO;
4091 
4092  PushID(label);
4093  BeginGroup();
4094 
4095  if (!(flags & ImGuiColorEditFlags_NoSidePreview))
4097 
4098  // Context menu: display and store options.
4099  if (!(flags & ImGuiColorEditFlags_NoOptions))
4100  ColorPickerOptionsPopup(col, flags);
4101 
4102  // Read stored options
4103  if (!(flags & ImGuiColorEditFlags__PickerMask))
4105  IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check that only 1 is selected
4106  if (!(flags & ImGuiColorEditFlags_NoOptions))
4108 
4109  // Setup
4110  int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4;
4111  bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha);
4112  ImVec2 picker_pos = window->DC.CursorPos;
4113  float square_sz = GetFrameHeight();
4114  float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars
4115  float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
4116  float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
4117  float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
4118  float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f);
4119 
4120  float backup_initial_col[4];
4121  memcpy(backup_initial_col, col, components * sizeof(float));
4122 
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);
4127 
4128  // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic.
4129  float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);
4130  ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point.
4131  ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point.
4132  ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point.
4133 
4134  float H,S,V;
4135  ColorConvertRGBtoHSV(col[0], col[1], col[2], H, S, V);
4136 
4137  bool value_changed = false, value_changed_h = false, value_changed_sv = false;
4138 
4141  {
4142  // Hue wheel + SV triangle logic
4143  InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));
4144  if (IsItemActive())
4145  {
4146  ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
4147  ImVec2 current_off = g.IO.MousePos - wheel_center;
4148  float initial_dist2 = ImLengthSqr(initial_off);
4149  if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1))
4150  {
4151  // Interactive with Hue wheel
4152  H = ImAtan2(current_off.y, current_off.x) / IM_PI*0.5f;
4153  if (H < 0.0f)
4154  H += 1.0f;
4155  value_changed = value_changed_h = true;
4156  }
4157  float cos_hue_angle = ImCos(-H * 2.0f * IM_PI);
4158  float sin_hue_angle = ImSin(-H * 2.0f * IM_PI);
4159  if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle)))
4160  {
4161  // Interacting with SV triangle
4162  ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle);
4163  if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated))
4164  current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);
4165  float uu, vv, ww;
4166  ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww);
4167  V = ImClamp(1.0f - vv, 0.0001f, 1.0f);
4168  S = ImClamp(uu / V, 0.0001f, 1.0f);
4169  value_changed = value_changed_sv = true;
4170  }
4171  }
4172  if (!(flags & ImGuiColorEditFlags_NoOptions))
4173  OpenPopupOnItemClick("context");
4174  }
4175  else if (flags & ImGuiColorEditFlags_PickerHueBar)
4176  {
4177  // SV rectangle logic
4178  InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
4179  if (IsItemActive())
4180  {
4181  S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size-1));
4182  V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
4183  value_changed = value_changed_sv = true;
4184  }
4185  if (!(flags & ImGuiColorEditFlags_NoOptions))
4186  OpenPopupOnItemClick("context");
4187 
4188  // Hue bar logic
4189  SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
4190  InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
4191  if (IsItemActive())
4192  {
4193  H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
4194  value_changed = value_changed_h = true;
4195  }
4196  }
4197 
4198  // Alpha bar logic
4199  if (alpha_bar)
4200  {
4201  SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y));
4202  InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size));
4203  if (IsItemActive())
4204  {
4205  col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
4206  value_changed = true;
4207  }
4208  }
4209  PopItemFlag(); // ImGuiItemFlags_NoNav
4210 
4211  if (!(flags & ImGuiColorEditFlags_NoSidePreview))
4212  {
4213  SameLine(0, style.ItemInnerSpacing.x);
4214  BeginGroup();
4215  }
4216 
4217  if (!(flags & ImGuiColorEditFlags_NoLabel))
4218  {
4219  const char* label_display_end = FindRenderedTextEnd(label);
4220  if (label != label_display_end)
4221  {
4222  if ((flags & ImGuiColorEditFlags_NoSidePreview))
4223  SameLine(0, style.ItemInnerSpacing.x);
4224  TextUnformatted(label, label_display_end);
4225  }
4226  }
4227 
4228  if (!(flags & ImGuiColorEditFlags_NoSidePreview))
4229  {
4231  ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
4232  if ((flags & ImGuiColorEditFlags_NoLabel))
4233  Text("Current");
4235  if (ref_col != NULL)
4236  {
4237  Text("Original");
4238  ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]);
4240  {
4241  memcpy(col, ref_col, components * sizeof(float));
4242  value_changed = true;
4243  }
4244  }
4245  PopItemFlag();
4246  EndGroup();
4247  }
4248 
4249  // Convert back color to RGB
4250  if (value_changed_h || value_changed_sv)
4251  ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]);
4252 
4253  // R,G,B and H,S,V slider color editor
4254  bool value_changed_fix_hue_wrap = false;
4255  if ((flags & ImGuiColorEditFlags_NoInputs) == 0)
4256  {
4257  PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);
4259  ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker;
4260  if (flags & ImGuiColorEditFlags_RGB || (flags & ImGuiColorEditFlags__InputsMask) == 0)
4261  if (ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_RGB))
4262  {
4263  // FIXME: Hackily differenciating using the DragInt (ActiveId != 0 && !ActiveIdAllowOverlap) vs. using the InputText or DropTarget.
4264  // For the later we don't want to run the hue-wrap canceling code. If you are well versed in HSV picker please provide your input! (See #2050)
4265  value_changed_fix_hue_wrap = (g.ActiveId != 0 && !g.ActiveIdAllowOverlap);
4266  value_changed = true;
4267  }
4268  if (flags & ImGuiColorEditFlags_HSV || (flags & ImGuiColorEditFlags__InputsMask) == 0)
4269  value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_HSV);
4270  if (flags & ImGuiColorEditFlags_HEX || (flags & ImGuiColorEditFlags__InputsMask) == 0)
4271  value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_HEX);
4272  PopItemWidth();
4273  }
4274 
4275  // Try to cancel hue wrap (after ColorEdit4 call), if any
4276  if (value_changed_fix_hue_wrap)
4277  {
4278  float new_H, new_S, new_V;
4279  ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V);
4280  if (new_H <= 0 && H > 0)
4281  {
4282  if (new_V <= 0 && V != new_V)
4283  ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]);
4284  else if (new_S <= 0)
4285  ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]);
4286  }
4287  }
4288 
4289  ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
4290  ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
4291  ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 1.0f));
4292 
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) };
4294  ImVec2 sv_cursor_pos;
4295 
4297  {
4298  // Render Hue Wheel
4299  const float aeps = 1.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).
4300  const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12);
4301  for (int n = 0; n < 6; n++)
4302  {
4303  const float a0 = (n) /6.0f * 2.0f * IM_PI - aeps;
4304  const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
4305  const int vert_start_idx = draw_list->VtxBuffer.Size;
4306  draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
4307  draw_list->PathStroke(IM_COL32_WHITE, false, wheel_thickness);
4308  const int vert_end_idx = draw_list->VtxBuffer.Size;
4309 
4310  // Paint colors over existing vertices
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);
4313  ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]);
4314  }
4315 
4316  // Render Cursor + preview on Hue Wheel
4317  float cos_hue_angle = ImCos(H * 2.0f * IM_PI);
4318  float sin_hue_angle = ImSin(H * 2.0f * IM_PI);
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.4f), 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);
4324  draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, IM_COL32_WHITE, hue_cursor_segments);
4325 
4326  // Render SV triangle (rotated according to hue)
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);
4330  ImVec2 uv_white = GetFontTexUvWhitePixel();
4331  draw_list->PrimReserve(6, 6);
4332  draw_list->PrimVtx(tra, uv_white, hue_color32);
4333  draw_list->PrimVtx(trb, uv_white, hue_color32);
4334  draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE);
4335  draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS);
4336  draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK);
4337  draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS);
4338  draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f);
4339  sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
4340  }
4341  else if (flags & ImGuiColorEditFlags_PickerHueBar)
4342  {
4343  // Render SV Square
4344  draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE);
4345  draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK);
4346  RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), 0.0f);
4347  sv_cursor_pos.x = ImClamp((float)(int)(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much
4348  sv_cursor_pos.y = ImClamp((float)(int)(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2);
4349 
4350  // Render Hue Bar
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);
4354  RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);
4355  RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);
4356  }
4357 
4358  // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
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);
4362  draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, IM_COL32_WHITE, 12);
4363 
4364  // Render alpha bar
4365  if (alpha_bar)
4366  {
4367  float alpha = ImSaturate(col[3]);
4368  ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
4369  RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
4370  draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, col32_no_alpha, col32_no_alpha, col32_no_alpha & ~IM_COL32_A_MASK, col32_no_alpha & ~IM_COL32_A_MASK);
4371  float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f);
4372  RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
4373  RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);
4374  }
4375 
4376  EndGroup();
4377 
4378  if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0)
4379  value_changed = false;
4380  if (value_changed)
4381  MarkItemEdited(window->DC.LastItemId);
4382 
4383  PopID();
4384 
4385  return value_changed;
4386 }
4387 
4388 // A little colored square. Return true when clicked.
4389 // FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip.
4390 // 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip.
4391 bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, ImVec2 size)
4392 {
4393  ImGuiWindow* window = GetCurrentWindow();
4394  if (window->SkipItems)
4395  return false;
4396 
4397  ImGuiContext& g = *GImGui;
4398  const ImGuiID id = window->GetID(desc_id);
4399  float default_size = GetFrameHeight();
4400  if (size.x == 0.0f)
4401  size.x = default_size;
4402  if (size.y == 0.0f)
4403  size.y = default_size;
4404  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
4405  ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f);
4406  if (!ItemAdd(bb, id))
4407  return false;
4408 
4409  bool hovered, held;
4410  bool pressed = ButtonBehavior(bb, id, &hovered, &held);
4411 
4412  if (flags & ImGuiColorEditFlags_NoAlpha)
4414 
4415  ImVec4 col_without_alpha(col.x, col.y, col.z, 1.0f);
4416  float grid_step = ImMin(size.x, size.y) / 2.99f;
4417  float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
4418  ImRect bb_inner = bb;
4419  float off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts.
4420  bb_inner.Expand(off);
4421  if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col.w < 1.0f)
4422  {
4423  float mid_x = (float)(int)((bb_inner.Min.x + bb_inner.Max.x) * 0.5f + 0.5f);
4424  RenderColorRectWithAlphaCheckerboard(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight);
4425  window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft);
4426  }
4427  else
4428  {
4429  // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha
4430  ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col : col_without_alpha;
4431  if (col_source.w < 1.0f)
4432  RenderColorRectWithAlphaCheckerboard(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding);
4433  else
4434  window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding, ImDrawCornerFlags_All);
4435  }
4436  RenderNavHighlight(bb, id);
4437  if (g.Style.FrameBorderSize > 0.0f)
4438  RenderFrameBorder(bb.Min, bb.Max, rounding);
4439  else
4440  window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border
4441 
4442  // Drag and Drop Source
4443  // NB: The ActiveId test is merely an optional micro-optimization, BeginDragDropSource() does the same test.
4444  if (g.ActiveId == id && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropSource())
4445  {
4446  if (flags & ImGuiColorEditFlags_NoAlpha)
4448  else
4450  ColorButton(desc_id, col, flags);
4451  SameLine();
4452  TextUnformatted("Color");
4454  }
4455 
4456  // Tooltip
4457  if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered)
4459 
4460  if (pressed)
4461  MarkItemEdited(id);
4462 
4463  return pressed;
4464 }
4465 
4467 {
4468  ImGuiContext& g = *GImGui;
4469  if ((flags & ImGuiColorEditFlags__InputsMask) == 0)
4471  if ((flags & ImGuiColorEditFlags__DataTypeMask) == 0)
4473  if ((flags & ImGuiColorEditFlags__PickerMask) == 0)
4475  IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__InputsMask))); // Check only 1 option is selected
4476  IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__DataTypeMask))); // Check only 1 option is selected
4477  IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check only 1 option is selected
4478  g.ColorEditOptions = flags;
4479 }
4480 
4481 // Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
4482 void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags)
4483 {
4484  ImGuiContext& g = *GImGui;
4485 
4486  int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
4487  BeginTooltipEx(0, true);
4488 
4489  const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
4490  if (text_end > text)
4491  {
4492  TextUnformatted(text, text_end);
4493  Separator();
4494  }
4495 
4496  ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2);
4498  SameLine();
4499  if (flags & ImGuiColorEditFlags_NoAlpha)
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]);
4501  else
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]);
4503  EndTooltip();
4504 }
4505 
4507 {
4508  bool allow_opt_inputs = !(flags & ImGuiColorEditFlags__InputsMask);
4509  bool allow_opt_datatype = !(flags & ImGuiColorEditFlags__DataTypeMask);
4510  if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context"))
4511  return;
4512  ImGuiContext& g = *GImGui;
4514  if (allow_opt_inputs)
4515  {
4519  }
4520  if (allow_opt_datatype)
4521  {
4522  if (allow_opt_inputs) Separator();
4524  if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Float;
4525  }
4526 
4527  if (allow_opt_inputs || allow_opt_datatype)
4528  Separator();
4529  if (Button("Copy as..", ImVec2(-1,0)))
4530  OpenPopup("Copy");
4531  if (BeginPopup("Copy"))
4532  {
4533  int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
4534  char buf[64];
4535  ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
4536  if (Selectable(buf))
4537  SetClipboardText(buf);
4538  ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca);
4539  if (Selectable(buf))
4540  SetClipboardText(buf);
4541  if (flags & ImGuiColorEditFlags_NoAlpha)
4542  ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X", cr, cg, cb);
4543  else
4544  ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X%02X", cr, cg, cb, ca);
4545  if (Selectable(buf))
4546  SetClipboardText(buf);
4547  EndPopup();
4548  }
4549 
4550  g.ColorEditOptions = opts;
4551  EndPopup();
4552 }
4553 
4554 void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags)
4555 {
4556  bool allow_opt_picker = !(flags & ImGuiColorEditFlags__PickerMask);
4557  bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar);
4558  if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context"))
4559  return;
4560  ImGuiContext& g = *GImGui;
4561  if (allow_opt_picker)
4562  {
4563  ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function
4564  PushItemWidth(picker_size.x);
4565  for (int picker_type = 0; picker_type < 2; picker_type++)
4566  {
4567  // Draw small/thumbnail version of each picker type (over an invisible button for selection)
4568  if (picker_type > 0) Separator();
4569  PushID(picker_type);
4571  if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar;
4572  if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;
4573  ImVec2 backup_pos = GetCursorScreenPos();
4574  if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup
4576  SetCursorScreenPos(backup_pos);
4577  ImVec4 dummy_ref_col;
4578  memcpy(&dummy_ref_col.x, ref_col, sizeof(float) * (picker_flags & ImGuiColorEditFlags_NoAlpha ? 3 : 4));
4579  ColorPicker4("##dummypicker", &dummy_ref_col.x, picker_flags);
4580  PopID();
4581  }
4582  PopItemWidth();
4583  }
4584  if (allow_opt_alpha_bar)
4585  {
4586  if (allow_opt_picker) Separator();
4587  CheckboxFlags("Alpha Bar", (unsigned int*)&g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
4588  }
4589  EndPopup();
4590 }
4591 
4592 //-------------------------------------------------------------------------
4593 // [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
4594 //-------------------------------------------------------------------------
4595 // - TreeNode()
4596 // - TreeNodeV()
4597 // - TreeNodeEx()
4598 // - TreeNodeExV()
4599 // - TreeNodeBehavior() [Internal]
4600 // - TreePush()
4601 // - TreePop()
4602 // - TreeAdvanceToLabelPos()
4603 // - GetTreeNodeToLabelSpacing()
4604 // - SetNextTreeNodeOpen()
4605 // - CollapsingHeader()
4606 //-------------------------------------------------------------------------
4607 
4608 bool ImGui::TreeNode(const char* str_id, const char* fmt, ...)
4609 {
4610  va_list args;
4611  va_start(args, fmt);
4612  bool is_open = TreeNodeExV(str_id, 0, fmt, args);
4613  va_end(args);
4614  return is_open;
4615 }
4616 
4617 bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...)
4618 {
4619  va_list args;
4620  va_start(args, fmt);
4621  bool is_open = TreeNodeExV(ptr_id, 0, fmt, args);
4622  va_end(args);
4623  return is_open;
4624 }
4625 
4626 bool ImGui::TreeNode(const char* label)
4627 {
4628  ImGuiWindow* window = GetCurrentWindow();
4629  if (window->SkipItems)
4630  return false;
4631  return TreeNodeBehavior(window->GetID(label), 0, label, NULL);
4632 }
4633 
4634 bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args)
4635 {
4636  return TreeNodeExV(str_id, 0, fmt, args);
4637 }
4638 
4639 bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args)
4640 {
4641  return TreeNodeExV(ptr_id, 0, fmt, args);
4642 }
4643 
4644 bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags)
4645 {
4646  ImGuiWindow* window = GetCurrentWindow();
4647  if (window->SkipItems)
4648  return false;
4649 
4650  return TreeNodeBehavior(window->GetID(label), flags, label, NULL);
4651 }
4652 
4653 bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
4654 {
4655  va_list args;
4656  va_start(args, fmt);
4657  bool is_open = TreeNodeExV(str_id, flags, fmt, args);
4658  va_end(args);
4659  return is_open;
4660 }
4661 
4662 bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
4663 {
4664  va_list args;
4665  va_start(args, fmt);
4666  bool is_open = TreeNodeExV(ptr_id, flags, fmt, args);
4667  va_end(args);
4668  return is_open;
4669 }
4670 
4671 bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
4672 {
4673  ImGuiWindow* window = GetCurrentWindow();
4674  if (window->SkipItems)
4675  return false;
4676 
4677  ImGuiContext& g = *GImGui;
4678  const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
4679  return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end);
4680 }
4681 
4682 bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
4683 {
4684  ImGuiWindow* window = GetCurrentWindow();
4685  if (window->SkipItems)
4686  return false;
4687 
4688  ImGuiContext& g = *GImGui;
4689  const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
4690  return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end);
4691 }
4692 
4694 {
4695  if (flags & ImGuiTreeNodeFlags_Leaf)
4696  return true;
4697 
4698  // We only write to the tree storage if the user clicks (or explicitly use SetNextTreeNode*** functions)
4699  ImGuiContext& g = *GImGui;
4700  ImGuiWindow* window = g.CurrentWindow;
4701  ImGuiStorage* storage = window->DC.StateStorage;
4702 
4703  bool is_open;
4704  if (g.NextTreeNodeOpenCond != 0)
4705  {
4707  {
4708  is_open = g.NextTreeNodeOpenVal;
4709  storage->SetInt(id, is_open);
4710  }
4711  else
4712  {
4713  // We treat ImGuiCond_Once and ImGuiCond_FirstUseEver the same because tree node state are not saved persistently.
4714  const int stored_value = storage->GetInt(id, -1);
4715  if (stored_value == -1)
4716  {
4717  is_open = g.NextTreeNodeOpenVal;
4718  storage->SetInt(id, is_open);
4719  }
4720  else
4721  {
4722  is_open = stored_value != 0;
4723  }
4724  }
4725  g.NextTreeNodeOpenCond = 0;
4726  }
4727  else
4728  {
4729  is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0;
4730  }
4731 
4732  // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior).
4733  // NB- If we are above max depth we still allow manually opened nodes to be logged.
4735  is_open = true;
4736 
4737  return is_open;
4738 }
4739 
4740 bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)
4741 {
4742  ImGuiWindow* window = GetCurrentWindow();
4743  if (window->SkipItems)
4744  return false;
4745 
4746  ImGuiContext& g = *GImGui;
4747  const ImGuiStyle& style = g.Style;
4748  const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0;
4749  const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f);
4750 
4751  if (!label_end)
4752  label_end = FindRenderedTextEnd(label);
4753  const ImVec2 label_size = CalcTextSize(label, label_end, false);
4754 
4755  // We vertically grow up to current line height up the typical widget height.
4756  const float text_base_offset_y = ImMax(padding.y, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
4757  const float frame_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
4758  ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height));
4759  if (display_frame)
4760  {
4761  // Framed header expand a little outside the default padding
4762  frame_bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1;
4763  frame_bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1;
4764  }
4765 
4766  const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing
4767  const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
4768  ItemSize(ImVec2(text_width, frame_height), text_base_offset_y);
4769 
4770  // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
4771  // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not)
4772  const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y);
4773  bool is_open = TreeNodeBehaviorIsOpen(id, flags);
4774  bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
4775 
4776  // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child.
4777  // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
4778  // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
4780  window->DC.TreeDepthMayJumpToParentOnPop |= (1 << window->DC.TreeDepth);
4781 
4782  bool item_add = ItemAdd(interact_bb, id);
4784  window->DC.LastItemDisplayRect = frame_bb;
4785 
4786  if (!item_add)
4787  {
4788  if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
4789  TreePushRawID(id);
4790  IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
4791  return is_open;
4792  }
4793 
4794  // Flags that affects opening behavior:
4795  // - 0(default) ..................... single-click anywhere to open
4796  // - OpenOnDoubleClick .............. double-click anywhere to open
4797  // - OpenOnArrow .................... single-click on arrow to open
4798  // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open
4800  if (!is_leaf)
4804 
4805  bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags);
4806  if (!is_leaf)
4807  {
4808  bool toggled = false;
4809  if (pressed)
4810  {
4812  if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
4813  toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)) && (!g.NavDisableMouseHover);
4815  toggled |= g.IO.MouseDoubleClicked[0];
4816  if (g.DragDropActive && is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again.
4817  toggled = false;
4818  }
4819 
4820  if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Left && is_open)
4821  {
4822  toggled = true;
4824  }
4825  if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority?
4826  {
4827  toggled = true;
4829  }
4830 
4831  if (toggled)
4832  {
4833  is_open = !is_open;
4834  window->DC.StateStorage->SetInt(id, is_open);
4835  }
4836  }
4839 
4840  // Render
4841  const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
4842  const ImVec2 text_pos = frame_bb.Min + ImVec2(text_offset_x, text_base_offset_y);
4843  if (display_frame)
4844  {
4845  // Framed type
4846  RenderFrame(frame_bb.Min, frame_bb.Max, col, true, style.FrameRounding);
4848  RenderArrow(frame_bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
4849  if (g.LogEnabled)
4850  {
4851  // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
4852  const char log_prefix[] = "\n##";
4853  const char log_suffix[] = "##";
4854  LogRenderedText(&text_pos, log_prefix, log_prefix+3);
4855  RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
4856  LogRenderedText(&text_pos, log_suffix+1, log_suffix+3);
4857  }
4858  else
4859  {
4860  RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
4861  }
4862  }
4863  else
4864  {
4865  // Unframed typed for tree nodes
4866  if (hovered || (flags & ImGuiTreeNodeFlags_Selected))
4867  {
4868  RenderFrame(frame_bb.Min, frame_bb.Max, col, false);
4870  }
4871 
4872  if (flags & ImGuiTreeNodeFlags_Bullet)
4873  RenderBullet(frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y));
4874  else if (!is_leaf)
4875  RenderArrow(frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
4876  if (g.LogEnabled)
4877  LogRenderedText(&text_pos, ">");
4878  RenderText(text_pos, label, label_end, false);
4879  }
4880 
4881  if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
4882  TreePushRawID(id);
4883  IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
4884  return is_open;
4885 }
4886 
4887 void ImGui::TreePush(const char* str_id)
4888 {
4889  ImGuiWindow* window = GetCurrentWindow();
4890  Indent();
4891  window->DC.TreeDepth++;
4892  PushID(str_id ? str_id : "#TreePush");
4893 }
4894 
4895 void ImGui::TreePush(const void* ptr_id)
4896 {
4897  ImGuiWindow* window = GetCurrentWindow();
4898  Indent();
4899  window->DC.TreeDepth++;
4900  PushID(ptr_id ? ptr_id : (const void*)"#TreePush");
4901 }
4902 
4904 {
4905  ImGuiWindow* window = GetCurrentWindow();
4906  Indent();
4907  window->DC.TreeDepth++;
4908  window->IDStack.push_back(id);
4909 }
4910 
4912 {
4913  ImGuiContext& g = *GImGui;
4914  ImGuiWindow* window = g.CurrentWindow;
4915  Unindent();
4916 
4917  window->DC.TreeDepth--;
4918  if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
4919  if (g.NavIdIsAlive && (window->DC.TreeDepthMayJumpToParentOnPop & (1 << window->DC.TreeDepth)))
4920  {
4921  SetNavID(window->IDStack.back(), g.NavLayer);
4923  }
4924  window->DC.TreeDepthMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1;
4925 
4926  IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
4927  PopID();
4928 }
4929 
4931 {
4932  ImGuiContext& g = *GImGui;
4934 }
4935 
4936 // Horizontal distance preceding label when using TreeNode() or Bullet()
4938 {
4939  ImGuiContext& g = *GImGui;
4940  return g.FontSize + (g.Style.FramePadding.x * 2.0f);
4941 }
4942 
4943 void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiCond cond)
4944 {
4945  ImGuiContext& g = *GImGui;
4946  if (g.CurrentWindow->SkipItems)
4947  return;
4948  g.NextTreeNodeOpenVal = is_open;
4949  g.NextTreeNodeOpenCond = cond ? cond : ImGuiCond_Always;
4950 }
4951 
4952 // CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag).
4953 // This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode().
4954 bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags)
4955 {
4956  ImGuiWindow* window = GetCurrentWindow();
4957  if (window->SkipItems)
4958  return false;
4959 
4960  return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label);
4961 }
4962 
4963 bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags)
4964 {
4965  ImGuiWindow* window = GetCurrentWindow();
4966  if (window->SkipItems)
4967  return false;
4968 
4969  if (p_open && !*p_open)
4970  return false;
4971 
4972  ImGuiID id = window->GetID(label);
4973  bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap : 0), label);
4974  if (p_open)
4975  {
4976  // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc.
4977  ImGuiContext& g = *GImGui;
4978  ImGuiItemHoveredDataBackup last_item_backup;
4979  float button_radius = g.FontSize * 0.5f;
4980  ImVec2 button_center = ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_radius, window->DC.LastItemRect.GetCenter().y);
4981  if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), button_center, button_radius))
4982  *p_open = false;
4983  last_item_backup.Restore();
4984  }
4985 
4986  return is_open;
4987 }
4988 
4989 //-------------------------------------------------------------------------
4990 // [SECTION] Widgets: Selectable
4991 //-------------------------------------------------------------------------
4992 // - Selectable()
4993 //-------------------------------------------------------------------------
4994 
4995 // Tip: pass a non-visible label (e.g. "##dummy") then you can use the space to draw other text or image.
4996 // But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id.
4997 bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
4998 {
4999  ImGuiWindow* window = GetCurrentWindow();
5000  if (window->SkipItems)
5001  return false;
5002 
5003  ImGuiContext& g = *GImGui;
5004  const ImGuiStyle& style = g.Style;
5005 
5006  if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) // FIXME-OPT: Avoid if vertically clipped.
5007  PopClipRect();
5008 
5009  ImGuiID id = window->GetID(label);
5010  ImVec2 label_size = CalcTextSize(label, NULL, true);
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);
5012  ImVec2 pos = window->DC.CursorPos;
5013  pos.y += window->DC.CurrentLineTextBaseOffset;
5014  ImRect bb_inner(pos, pos + size);
5015  ItemSize(bb_inner);
5016 
5017  // Fill horizontal space.
5018  ImVec2 window_padding = window->WindowPadding;
5020  float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - window->DC.CursorPos.x);
5021  ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y);
5022  ImRect bb(pos, pos + size_draw);
5023  if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth))
5024  bb.Max.x += window_padding.x;
5025 
5026  // Selectables are tightly packed together, we extend the box to cover spacing between selectable.
5027  float spacing_L = (float)(int)(style.ItemSpacing.x * 0.5f);
5028  float spacing_U = (float)(int)(style.ItemSpacing.y * 0.5f);
5029  float spacing_R = style.ItemSpacing.x - spacing_L;
5030  float spacing_D = style.ItemSpacing.y - spacing_U;
5031  bb.Min.x -= spacing_L;
5032  bb.Min.y -= spacing_U;
5033  bb.Max.x += spacing_R;
5034  bb.Max.y += spacing_D;
5035  if (!ItemAdd(bb, id))
5036  {
5037  if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet)
5039  return false;
5040  }
5041 
5042  // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries
5043  ImGuiButtonFlags button_flags = 0;
5047  if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled;
5049  bool hovered, held;
5050  bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
5051  if (flags & ImGuiSelectableFlags_Disabled)
5052  selected = false;
5053 
5054  // Hovering selectable with mouse updates NavId accordingly so navigation can be resumed with gamepad/keyboard (this doesn't happen on most widgets)
5055  if (pressed || hovered)
5056  if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
5057  {
5058  g.NavDisableHighlight = true;
5059  SetNavID(id, window->DC.NavLayerCurrent);
5060  }
5061  if (pressed)
5062  MarkItemEdited(id);
5063 
5064  // Render
5065  if (hovered || selected)
5066  {
5067  const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
5068  RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
5070  }
5071 
5072  if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet)
5073  {
5075  bb.Max.x -= (GetContentRegionMax().x - max_x);
5076  }
5077 
5079  RenderTextClipped(bb_inner.Min, bb.Max, label, NULL, &label_size, ImVec2(0.0f,0.0f));
5081 
5082  // Automatically close popups
5085  return pressed;
5086 }
5087 
5088 bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
5089 {
5090  if (Selectable(label, *p_selected, flags, size_arg))
5091  {
5092  *p_selected = !*p_selected;
5093  return true;
5094  }
5095  return false;
5096 }
5097 
5098 //-------------------------------------------------------------------------
5099 // [SECTION] Widgets: ListBox
5100 //-------------------------------------------------------------------------
5101 // - ListBox()
5102 // - ListBoxHeader()
5103 // - ListBoxFooter()
5104 //-------------------------------------------------------------------------
5105 
5106 // FIXME: In principle this function should be called BeginListBox(). We should rename it after re-evaluating if we want to keep the same signature.
5107 // Helper to calculate the size of a listbox and display a label on the right.
5108 // Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an non-visible label e.g. "##empty"
5109 bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
5110 {
5111  ImGuiWindow* window = GetCurrentWindow();
5112  if (window->SkipItems)
5113  return false;
5114 
5115  const ImGuiStyle& style = GetStyle();
5116  const ImGuiID id = GetID(label);
5117  const ImVec2 label_size = CalcTextSize(label, NULL, true);
5118 
5119  // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
5120  ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y);
5121  ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
5122  ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
5123  ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
5124  window->DC.LastItemRect = bb; // Forward storage for ListBoxFooter.. dodgy.
5125 
5126  BeginGroup();
5127  if (label_size.x > 0)
5128  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
5129 
5130  BeginChildFrame(id, frame_bb.GetSize());
5131  return true;
5132 }
5133 
5134 // FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature.
5135 bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
5136 {
5137  // Size default to hold ~7.25 items.
5138  // We add +25% worth of item height to allow the user to see at a glance if there are more items up/down, without looking at the scrollbar.
5139  // We don't add this extra bit if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic list of items will make the widget resize occasionally when it crosses that size.
5140  // I am expecting that someone will come and complain about this behavior in a remote future, then we can advise on a better solution.
5141  if (height_in_items < 0)
5142  height_in_items = ImMin(items_count, 7);
5143  const ImGuiStyle& style = GetStyle();
5144  float height_in_items_f = (height_in_items < items_count) ? (height_in_items + 0.25f) : (height_in_items + 0.00f);
5145 
5146  // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild().
5147  ImVec2 size;
5148  size.x = 0.0f;
5149  size.y = GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f;
5150  return ListBoxHeader(label, size);
5151 }
5152 
5153 // FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature.
5155 {
5156  ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow;
5157  const ImRect bb = parent_window->DC.LastItemRect;
5158  const ImGuiStyle& style = GetStyle();
5159 
5160  EndChildFrame();
5161 
5162  // Redeclare item size so that it includes the label (we have stored the full size in LastItemRect)
5163  // We call SameLine() to restore DC.CurrentLine* data
5164  SameLine();
5165  parent_window->DC.CursorPos = bb.Min;
5166  ItemSize(bb, style.FramePadding.y);
5167  EndGroup();
5168 }
5169 
5170 bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items)
5171 {
5172  const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items);
5173  return value_changed;
5174 }
5175 
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)
5177 {
5178  if (!ListBoxHeader(label, items_count, height_in_items))
5179  return false;
5180 
5181  // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper.
5182  ImGuiContext& g = *GImGui;
5183  bool value_changed = false;
5184  ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to.
5185  while (clipper.Step())
5186  for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
5187  {
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*";
5192 
5193  PushID(i);
5194  if (Selectable(item_text, item_selected))
5195  {
5196  *current_item = i;
5197  value_changed = true;
5198  }
5199  if (item_selected)
5201  PopID();
5202  }
5203  ListBoxFooter();
5204  if (value_changed)
5206 
5207  return value_changed;
5208 }
5209 
5210 //-------------------------------------------------------------------------
5211 // [SECTION] Widgets: PlotLines, PlotHistogram
5212 //-------------------------------------------------------------------------
5213 // - PlotEx() [Internal]
5214 // - PlotLines()
5215 // - PlotHistogram()
5216 //-------------------------------------------------------------------------
5217 
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)
5219 {
5220  ImGuiWindow* window = GetCurrentWindow();
5221  if (window->SkipItems)
5222  return;
5223 
5224  ImGuiContext& g = *GImGui;
5225  const ImGuiStyle& style = g.Style;
5226 
5227  const ImVec2 label_size = CalcTextSize(label, NULL, true);
5228  if (graph_size.x == 0.0f)
5229  graph_size.x = CalcItemWidth();
5230  if (graph_size.y == 0.0f)
5231  graph_size.y = label_size.y + (style.FramePadding.y * 2);
5232 
5233  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y));
5234  const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
5235  const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0));
5236  ItemSize(total_bb, style.FramePadding.y);
5237  if (!ItemAdd(total_bb, 0, &frame_bb))
5238  return;
5239  const bool hovered = ItemHoverable(inner_bb, 0);
5240 
5241  // Determine scale from values if not specified
5242  if (scale_min == FLT_MAX || scale_max == FLT_MAX)
5243  {
5244  float v_min = FLT_MAX;
5245  float v_max = -FLT_MAX;
5246  for (int i = 0; i < values_count; i++)
5247  {
5248  const float v = values_getter(data, i);
5249  v_min = ImMin(v_min, v);
5250  v_max = ImMax(v_max, v);
5251  }
5252  if (scale_min == FLT_MAX)
5253  scale_min = v_min;
5254  if (scale_max == FLT_MAX)
5255  scale_max = v_max;
5256  }
5257 
5258  RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
5259 
5260  if (values_count > 0)
5261  {
5262  int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
5263  int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
5264 
5265  // Tooltip on hover
5266  int v_hovered = -1;
5267  if (hovered)
5268  {
5269  const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
5270  const int v_idx = (int)(t * item_count);
5271  IM_ASSERT(v_idx >= 0 && v_idx < values_count);
5272 
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);
5275  if (plot_type == ImGuiPlotType_Lines)
5276  SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1);
5277  else if (plot_type == ImGuiPlotType_Histogram)
5278  SetTooltip("%d: %8.4g", v_idx, v0);
5279  v_hovered = v_idx;
5280  }
5281 
5282  const float t_step = 1.0f / (float)res_w;
5283  const float inv_scale = (scale_min == scale_max) ? 0.0f : (1.0f / (scale_max - scale_min));
5284 
5285  float v0 = values_getter(data, (0 + values_offset) % values_count);
5286  float t0 = 0.0f;
5287  ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle
5288  float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands
5289 
5290  const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
5292 
5293  for (int n = 0; n < res_w; n++)
5294  {
5295  const float t1 = t0 + t_step;
5296  const int v1_idx = (int)(t0 * item_count + 0.5f);
5297  IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
5298  const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
5299  const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) );
5300 
5301  // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
5302  ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
5303  ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t));
5304  if (plot_type == ImGuiPlotType_Lines)
5305  {
5306  window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
5307  }
5308  else if (plot_type == ImGuiPlotType_Histogram)
5309  {
5310  if (pos1.x >= pos0.x + 2.0f)
5311  pos1.x -= 1.0f;
5312  window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
5313  }
5314 
5315  t0 = t1;
5316  tp0 = tp1;
5317  }
5318  }
5319 
5320  // Text overlay
5321  if (overlay_text)
5322  RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f,0.0f));
5323 
5324  if (label_size.x > 0.0f)
5325  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
5326 }
5327 
5329 {
5330  const float* Values;
5331  int Stride;
5332 
5333  ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; }
5334 };
5335 
5336 static float Plot_ArrayGetter(void* data, int idx)
5337 {
5339  const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride);
5340  return v;
5341 }
5342 
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)
5344 {
5345  ImGuiPlotArrayGetterData data(values, stride);
5346  PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5347 }
5348 
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)
5350 {
5351  PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5352 }
5353 
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)
5355 {
5356  ImGuiPlotArrayGetterData data(values, stride);
5357  PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5358 }
5359 
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)
5361 {
5362  PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5363 }
5364 
5365 //-------------------------------------------------------------------------
5366 // [SECTION] Widgets: Value helpers
5367 // Those is not very useful, legacy API.
5368 //-------------------------------------------------------------------------
5369 // - Value()
5370 //-------------------------------------------------------------------------
5371 
5372 void ImGui::Value(const char* prefix, bool b)
5373 {
5374  Text("%s: %s", prefix, (b ? "true" : "false"));
5375 }
5376 
5377 void ImGui::Value(const char* prefix, int v)
5378 {
5379  Text("%s: %d", prefix, v);
5380 }
5381 
5382 void ImGui::Value(const char* prefix, unsigned int v)
5383 {
5384  Text("%s: %d", prefix, v);
5385 }
5386 
5387 void ImGui::Value(const char* prefix, float v, const char* float_format)
5388 {
5389  if (float_format)
5390  {
5391  char fmt[64];
5392  ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format);
5393  Text(fmt, prefix, v);
5394  }
5395  else
5396  {
5397  Text("%s: %.3f", prefix, v);
5398  }
5399 }
5400 
5401 //-------------------------------------------------------------------------
5402 // [SECTION] MenuItem, BeginMenu, EndMenu, etc.
5403 //-------------------------------------------------------------------------
5404 // - ImGuiMenuColumns [Internal]
5405 // - BeginMainMenuBar()
5406 // - EndMainMenuBar()
5407 // - BeginMenuBar()
5408 // - EndMenuBar()
5409 // - BeginMenu()
5410 // - EndMenu()
5411 // - MenuItem()
5412 //-------------------------------------------------------------------------
5413 
5414 // Helpers for internal use
5416 {
5417  Count = 0;
5418  Spacing = Width = NextWidth = 0.0f;
5419  memset(Pos, 0, sizeof(Pos));
5420  memset(NextWidths, 0, sizeof(NextWidths));
5421 }
5422 
5423 void ImGuiMenuColumns::Update(int count, float spacing, bool clear)
5424 {
5426  Count = count;
5427  Width = NextWidth = 0.0f;
5428  Spacing = spacing;
5429  if (clear) memset(NextWidths, 0, sizeof(NextWidths));
5430  for (int i = 0; i < Count; i++)
5431  {
5432  if (i > 0 && NextWidths[i] > 0.0f)
5433  Width += Spacing;
5434  Pos[i] = (float)(int)Width;
5435  Width += NextWidths[i];
5436  NextWidths[i] = 0.0f;
5437  }
5438 }
5439 
5440 float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double
5441 {
5442  NextWidth = 0.0f;
5443  NextWidths[0] = ImMax(NextWidths[0], w0);
5444  NextWidths[1] = ImMax(NextWidths[1], w1);
5445  NextWidths[2] = ImMax(NextWidths[2], w2);
5446  for (int i = 0; i < 3; i++)
5447  NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f);
5448  return ImMax(Width, NextWidth);
5449 }
5450 
5452 {
5453  return ImMax(0.0f, avail_w - Width);
5454 }
5455 
5456 // For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set.
5458 {
5459  ImGuiContext& g = *GImGui;
5461  SetNextWindowPos(ImVec2(0.0f, 0.0f));
5466  bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar();
5467  PopStyleVar(2);
5469  if (!is_open)
5470  {
5471  End();
5472  return false;
5473  }
5474  return true;
5475 }
5476 
5478 {
5479  EndMenuBar();
5480 
5481  // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window
5482  ImGuiContext& g = *GImGui;
5483  if (g.CurrentWindow == g.NavWindow && g.NavLayer == 0)
5485 
5486  End();
5487 }
5488 
5490 {
5491  ImGuiWindow* window = GetCurrentWindow();
5492  if (window->SkipItems)
5493  return false;
5494  if (!(window->Flags & ImGuiWindowFlags_MenuBar))
5495  return false;
5496 
5497  IM_ASSERT(!window->DC.MenuBarAppending);
5498  BeginGroup(); // Backup position on layer 0
5499  PushID("##menubar");
5500 
5501  // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect.
5502  // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy.
5503  ImRect bar_rect = window->MenuBarRect();
5504  ImRect clip_rect(ImFloor(bar_rect.Min.x + 0.5f), ImFloor(bar_rect.Min.y + window->WindowBorderSize + 0.5f), ImFloor(ImMax(bar_rect.Min.x, bar_rect.Max.x - window->WindowRounding) + 0.5f), ImFloor(bar_rect.Max.y + 0.5f));
5505  clip_rect.ClipWith(window->OuterRectClipped);
5506  PushClipRect(clip_rect.Min, clip_rect.Max, false);
5507 
5508  window->DC.CursorPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffset.x, bar_rect.Min.y + window->DC.MenuBarOffset.y);
5511  window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
5512  window->DC.MenuBarAppending = true;
5514  return true;
5515 }
5516 
5518 {
5519  ImGuiWindow* window = GetCurrentWindow();
5520  if (window->SkipItems)
5521  return;
5522  ImGuiContext& g = *GImGui;
5523 
5524  // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings.
5526  {
5527  ImGuiWindow* nav_earliest_child = g.NavWindow;
5528  while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu))
5529  nav_earliest_child = nav_earliest_child->ParentWindow;
5530  if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && g.NavMoveRequestForward == ImGuiNavForward_None)
5531  {
5532  // To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
5533  // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost)
5534  IM_ASSERT(window->DC.NavLayerActiveMaskNext & 0x02); // Sanity check
5535  FocusWindow(window);
5536  SetNavIDWithRectRel(window->NavLastIds[1], 1, window->NavRectRel[1]);
5538  g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
5541  }
5542  }
5543 
5545  IM_ASSERT(window->DC.MenuBarAppending);
5546  PopClipRect();
5547  PopID();
5548  window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->MenuBarRect().Min.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
5549  window->DC.GroupStack.back().AdvanceCursor = false;
5550  EndGroup(); // Restore position on layer 0
5553  window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
5554  window->DC.MenuBarAppending = false;
5555 }
5556 
5557 bool ImGui::BeginMenu(const char* label, bool enabled)
5558 {
5559  ImGuiWindow* window = GetCurrentWindow();
5560  if (window->SkipItems)
5561  return false;
5562 
5563  ImGuiContext& g = *GImGui;
5564  const ImGuiStyle& style = g.Style;
5565  const ImGuiID id = window->GetID(label);
5566 
5567  ImVec2 label_size = CalcTextSize(label, NULL, true);
5568 
5569  bool pressed;
5570  bool menu_is_open = IsPopupOpen(id);
5571  bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
5572  ImGuiWindow* backed_nav_window = g.NavWindow;
5573  if (menuset_is_open)
5574  g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
5575 
5576  // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestWindowPosForPopup).
5577  ImVec2 popup_pos, pos = window->DC.CursorPos;
5578  if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
5579  {
5580  // Menu inside an horizontal menu bar
5581  // Selectable extend their highlight by half ItemSpacing in each direction.
5582  // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
5583  popup_pos = ImVec2(pos.x - 1.0f - (float)(int)(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight());
5584  window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);
5586  float w = label_size.x;
5588  PopStyleVar();
5589  window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
5590  }
5591  else
5592  {
5593  // Menu inside a menu
5594  popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
5595  float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame
5596  float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);
5599  RenderArrow(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), ImGuiDir_Right);
5600  if (!enabled) PopStyleColor();
5601  }
5602 
5603  const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id);
5604  if (menuset_is_open)
5605  g.NavWindow = backed_nav_window;
5606 
5607  bool want_open = false, want_close = false;
5608  if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
5609  {
5610  // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.
5611  bool moving_within_opened_triangle = false;
5612  if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].ParentWindow == window && !(window->Flags & ImGuiWindowFlags_MenuBar))
5613  {
5614  if (ImGuiWindow* next_window = g.OpenPopupStack[g.BeginPopupStack.Size].Window)
5615  {
5616  ImRect next_window_rect = next_window->Rect();
5617  ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta;
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();
5620  float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack.
5621  ta.x += (window->Pos.x < next_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues
5622  tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?
5623  tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f);
5624  moving_within_opened_triangle = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
5625  //window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); window->DrawList->PopClipRect(); // Debug
5626  }
5627  }
5628 
5629  want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle);
5630  want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed);
5631 
5632  if (g.NavActivateId == id)
5633  {
5634  want_close = menu_is_open;
5635  want_open = !menu_is_open;
5636  }
5637  if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
5638  {
5639  want_open = true;
5641  }
5642  }
5643  else
5644  {
5645  // Menu bar
5646  if (menu_is_open && pressed && menuset_is_open) // Click an open menu again to close it
5647  {
5648  want_close = true;
5649  want_open = menu_is_open = false;
5650  }
5651  else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // First click to open, then hover to open others
5652  {
5653  want_open = true;
5654  }
5655  else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open
5656  {
5657  want_open = true;
5659  }
5660  }
5661 
5662  if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }'
5663  want_close = true;
5664  if (want_close && IsPopupOpen(id))
5666 
5667  IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
5668 
5669  if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
5670  {
5671  // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame.
5672  OpenPopup(label);
5673  return false;
5674  }
5675 
5676  menu_is_open |= want_open;
5677  if (want_open)
5678  OpenPopup(label);
5679 
5680  if (menu_is_open)
5681  {
5682  // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
5683  SetNextWindowPos(popup_pos, ImGuiCond_Always);
5687  menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
5688  }
5689 
5690  return menu_is_open;
5691 }
5692 
5694 {
5695  // Nav: When a left move request _within our child menu_ failed, close ourselves (the _parent_ menu).
5696  // A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs.
5697  // However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction.
5698  ImGuiContext& g = *GImGui;
5699  ImGuiWindow* window = g.CurrentWindow;
5701  {
5704  }
5705 
5706  EndPopup();
5707 }
5708 
5709 bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled)
5710 {
5711  ImGuiWindow* window = GetCurrentWindow();
5712  if (window->SkipItems)
5713  return false;
5714 
5715  ImGuiContext& g = *GImGui;
5716  ImGuiStyle& style = g.Style;
5717  ImVec2 pos = window->DC.CursorPos;
5718  ImVec2 label_size = CalcTextSize(label, NULL, true);
5719 
5721  bool pressed;
5722  if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
5723  {
5724  // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
5725  // Note that in this situation we render neither the shortcut neither the selected tick mark
5726  float w = label_size.x;
5727  window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);
5729  pressed = Selectable(label, false, flags, ImVec2(w, 0.0f));
5730  PopStyleVar();
5731  window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
5732  }
5733  else
5734  {
5735  ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f);
5736  float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame
5737  float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);
5738  pressed = Selectable(label, false, flags | ImGuiSelectableFlags_DrawFillAvailWidth, ImVec2(w, 0.0f));
5739  if (shortcut_size.x > 0.0f)
5740  {
5742  RenderText(pos + ImVec2(window->MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false);
5743  PopStyleColor();
5744  }
5745  if (selected)
5746  RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f);
5747  }
5748 
5749  IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
5750  return pressed;
5751 }
5752 
5753 bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled)
5754 {
5755  if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled))
5756  {
5757  if (p_selected)
5758  *p_selected = !*p_selected;
5759  return true;
5760  }
5761  return false;
5762 }
5763 
5764 //-------------------------------------------------------------------------
5765 // [SECTION] Widgets: BeginTabBar, EndTabBar, etc.
5766 //-------------------------------------------------------------------------
5767 // [BETA API] API may evolve! This code has been extracted out of the Docking branch,
5768 // and some of the construct which are not used in Master may be left here to facilitate merging.
5769 //-------------------------------------------------------------------------
5770 // - BeginTabBar()
5771 // - BeginTabBarEx() [Internal]
5772 // - EndTabBar()
5773 // - TabBarLayout() [Internal]
5774 // - TabBarCalcTabID() [Internal]
5775 // - TabBarCalcMaxTabWidth() [Internal]
5776 // - TabBarFindTabById() [Internal]
5777 // - TabBarRemoveTab() [Internal]
5778 // - TabBarCloseTab() [Internal]
5779 // - TabBarScrollClamp()v
5780 // - TabBarScrollToTab() [Internal]
5781 // - TabBarQueueChangeTabOrder() [Internal]
5782 // - TabBarScrollingButtons() [Internal]
5783 //-------------------------------------------------------------------------
5784 
5785 namespace ImGui
5786 {
5787  static void TabBarLayout(ImGuiTabBar* tab_bar);
5788  static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label);
5789  static float TabBarCalcMaxTabWidth();
5790  static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling);
5791  static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
5793 }
5794 
5796 {
5797  ID = 0;
5800  OffsetMax = OffsetNextTab = 0.0f;
5801  ScrollingAnim = ScrollingTarget = 0.0f;
5803  ReorderRequestTabId = 0;
5804  ReorderRequestDir = 0;
5806  LastTabItemIdx = -1;
5807 }
5808 
5809 static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void* lhs, const void* rhs)
5810 {
5811  const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
5812  const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
5813  return (int)(a->Offset - b->Offset);
5814 }
5815 
5816 static int IMGUI_CDECL TabBarSortItemComparer(const void* lhs, const void* rhs)
5817 {
5818  const ImGuiTabBarSortItem* a = (const ImGuiTabBarSortItem*)lhs;
5819  const ImGuiTabBarSortItem* b = (const ImGuiTabBarSortItem*)rhs;
5820  if (int d = (int)(b->Width - a->Width))
5821  return d;
5822  return (b->Index - a->Index);
5823 }
5824 
5825 bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags)
5826 {
5827  ImGuiContext& g = *GImGui;
5828  ImGuiWindow* window = g.CurrentWindow;
5829  if (window->SkipItems)
5830  return false;
5831 
5832  ImGuiID id = window->GetID(str_id);
5833  ImGuiTabBar* tab_bar = g.TabBars.GetOrAddByKey(id);
5834  ImRect tab_bar_bb = ImRect(window->DC.CursorPos.x, window->DC.CursorPos.y, window->InnerClipRect.Max.x, window->DC.CursorPos.y + g.FontSize + g.Style.FramePadding.y * 2);
5835  tab_bar->ID = id;
5836  return BeginTabBarEx(tab_bar, tab_bar_bb, flags | ImGuiTabBarFlags_IsFocused);
5837 }
5838 
5839 bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImGuiTabBarFlags flags)
5840 {
5841  ImGuiContext& g = *GImGui;
5842  ImGuiWindow* window = g.CurrentWindow;
5843  if (window->SkipItems)
5844  return false;
5845 
5846  if ((flags & ImGuiTabBarFlags_DockNode) == 0)
5847  window->IDStack.push_back(tab_bar->ID);
5848 
5849  g.CurrentTabBar.push_back(tab_bar);
5850  if (tab_bar->CurrFrameVisible == g.FrameCount)
5851  {
5852  //IMGUI_DEBUG_LOG("BeginTabBarEx already called this frame\n", g.FrameCount);
5853  IM_ASSERT(0);
5854  return true;
5855  }
5856 
5857  // When toggling back from ordered to manually-reorderable, shuffle tabs to enforce the last visible order.
5858  // Otherwise, the most recently inserted tabs would move at the end of visible list which can be a little too confusing or magic for the user.
5859  if ((flags & ImGuiTabBarFlags_Reorderable) && !(tab_bar->Flags & ImGuiTabBarFlags_Reorderable) && tab_bar->Tabs.Size > 1 && tab_bar->PrevFrameVisible != -1)
5860  ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByVisibleOffset);
5861 
5862  // Flags
5863  if ((flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
5865 
5866  tab_bar->Flags = flags;
5867  tab_bar->BarRect = tab_bar_bb;
5868  tab_bar->WantLayout = true; // Layout will be done on the first call to ItemTab()
5869  tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible;
5870  tab_bar->CurrFrameVisible = g.FrameCount;
5871 
5872  // Layout
5873  ItemSize(ImVec2(tab_bar->OffsetMax, tab_bar->BarRect.GetHeight()));
5874  window->DC.CursorPos.x = tab_bar->BarRect.Min.x;
5875 
5876  // Draw separator
5878  const float y = tab_bar->BarRect.Max.y - 1.0f;
5879  {
5880  const float separator_min_x = tab_bar->BarRect.Min.x - ((flags & ImGuiTabBarFlags_DockNodeIsDockSpace) ? 0.0f : window->WindowPadding.x);
5881  const float separator_max_x = tab_bar->BarRect.Max.x + ((flags & ImGuiTabBarFlags_DockNodeIsDockSpace) ? 0.0f : window->WindowPadding.x);
5882  window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f);
5883  }
5884  return true;
5885 }
5886 
5888 {
5889  ImGuiContext& g = *GImGui;
5890  ImGuiWindow* window = g.CurrentWindow;
5891  if (window->SkipItems)
5892  return;
5893 
5894  IM_ASSERT(!g.CurrentTabBar.empty()); // Mismatched BeginTabBar/EndTabBar
5895  ImGuiTabBar* tab_bar = g.CurrentTabBar.back();
5896  if (tab_bar->WantLayout)
5897  TabBarLayout(tab_bar);
5898 
5899  // Restore the last visible height if no tab is visible, this reduce vertical flicker/movement when a tabs gets removed without calling SetTabItemClosed().
5900  const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
5901  if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing)
5902  tab_bar->ContentsHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, 0.0f);
5903  else
5904  window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->ContentsHeight;
5905 
5906  if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
5907  PopID();
5908  g.CurrentTabBar.pop_back();
5909 }
5910 
5911 // This is called only once a frame before by the first call to ItemTab()
5912 // The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions.
5913 static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
5914 {
5915  ImGuiContext& g = *GImGui;
5916  tab_bar->WantLayout = false;
5917 
5918  // Garbage collect
5919  int tab_dst_n = 0;
5920  for (int tab_src_n = 0; tab_src_n < tab_bar->Tabs.Size; tab_src_n++)
5921  {
5922  ImGuiTabItem* tab = &tab_bar->Tabs[tab_src_n];
5923  if (tab->LastFrameVisible < tab_bar->PrevFrameVisible)
5924  {
5925  if (tab->ID == tab_bar->SelectedTabId)
5926  tab_bar->SelectedTabId = 0;
5927  continue;
5928  }
5929  if (tab_dst_n != tab_src_n)
5930  tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n];
5931  tab_dst_n++;
5932  }
5933  if (tab_bar->Tabs.Size != tab_dst_n)
5934  tab_bar->Tabs.resize(tab_dst_n);
5935 
5936  // Setup next selected tab
5937  ImGuiID scroll_track_selected_tab_id = 0;
5938  if (tab_bar->NextSelectedTabId)
5939  {
5940  tab_bar->SelectedTabId = tab_bar->NextSelectedTabId;
5941  tab_bar->NextSelectedTabId = 0;
5942  scroll_track_selected_tab_id = tab_bar->SelectedTabId;
5943  }
5944 
5945  // Process order change request (we could probably process it when requested but it's just saner to do it in a single spot).
5946  if (tab_bar->ReorderRequestTabId != 0)
5947  {
5948  if (ImGuiTabItem* tab1 = TabBarFindTabByID(tab_bar, tab_bar->ReorderRequestTabId))
5949  {
5950  //IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
5951  int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestDir;
5952  if (tab2_order >= 0 && tab2_order < tab_bar->Tabs.Size)
5953  {
5954  ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order];
5955  ImGuiTabItem item_tmp = *tab1;
5956  *tab1 = *tab2;
5957  *tab2 = item_tmp;
5958  if (tab2->ID == tab_bar->SelectedTabId)
5959  scroll_track_selected_tab_id = tab2->ID;
5960  tab1 = tab2 = NULL;
5961  }
5962  if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings)
5964  }
5965  tab_bar->ReorderRequestTabId = 0;
5966  }
5967 
5968  ImVector<ImGuiTabBarSortItem>& width_sort_buffer = g.TabSortByWidthBuffer;
5969  width_sort_buffer.resize(tab_bar->Tabs.Size);
5970 
5971  // Compute ideal widths
5972  float width_total_contents = 0.0f;
5973  ImGuiTabItem* most_recently_selected_tab = NULL;
5974  bool found_selected_tab_id = false;
5975  for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
5976  {
5977  ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
5978  IM_ASSERT(tab->LastFrameVisible >= tab_bar->PrevFrameVisible);
5979 
5980  if (most_recently_selected_tab == NULL || most_recently_selected_tab->LastFrameSelected < tab->LastFrameSelected)
5981  most_recently_selected_tab = tab;
5982  if (tab->ID == tab_bar->SelectedTabId)
5983  found_selected_tab_id = true;
5984 
5985  // Refresh tab width immediately if we can (for manual tab bar, WidthContent will lag by one frame which is mostly noticeable when changing style.FramePadding.x)
5986  // Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
5987  // and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
5988  width_total_contents += (tab_n > 0 ? g.Style.ItemInnerSpacing.x : 0.0f) + tab->WidthContents;
5989 
5990  // Store data so we can build an array sorted by width if we need to shrink tabs down
5991  width_sort_buffer[tab_n].Index = tab_n;
5992  width_sort_buffer[tab_n].Width = tab->WidthContents;
5993  }
5994 
5995  // Compute width
5996  const float width_avail = tab_bar->BarRect.GetWidth();
5997  float width_excess = (width_avail < width_total_contents) ? (width_total_contents - width_avail) : 0.0f;
5998  if (width_excess > 0.0f && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown))
5999  {
6000  // If we don't have enough room, resize down the largest tabs first
6001  if (tab_bar->Tabs.Size > 1)
6002  ImQsort(width_sort_buffer.Data, (size_t)width_sort_buffer.Size, sizeof(ImGuiTabBarSortItem), TabBarSortItemComparer);
6003  int tab_count_same_width = 1;
6004  while (width_excess > 0.0f && tab_count_same_width < tab_bar->Tabs.Size)
6005  {
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;
6013  }
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;
6016  }
6017  else
6018  {
6019  const float tab_max_width = TabBarCalcMaxTabWidth();
6020  for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
6021  {
6022  ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
6023  tab->Width = ImMin(tab->WidthContents, tab_max_width);
6024  }
6025  }
6026 
6027  // Layout all active tabs
6028  float offset_x = 0.0f;
6029  for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
6030  {
6031  ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
6032  tab->Offset = offset_x;
6033  if (scroll_track_selected_tab_id == 0 && g.NavJustMovedToId == tab->ID)
6034  scroll_track_selected_tab_id = tab->ID;
6035  offset_x += tab->Width + g.Style.ItemInnerSpacing.x;
6036  }
6037  tab_bar->OffsetMax = ImMax(offset_x - g.Style.ItemInnerSpacing.x, 0.0f);
6038  tab_bar->OffsetNextTab = 0.0f;
6039 
6040  // Horizontal scrolling buttons
6041  const bool scrolling_buttons = (tab_bar->OffsetMax > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll);
6042  if (scrolling_buttons)
6043  if (ImGuiTabItem* tab_to_select = TabBarScrollingButtons(tab_bar)) // NB: Will alter BarRect.Max.x!
6044  scroll_track_selected_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
6045 
6046  // If we have lost the selected tab, select the next most recently active one
6047  if (found_selected_tab_id == false)
6048  tab_bar->SelectedTabId = 0;
6049  if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL)
6050  scroll_track_selected_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID;
6051 
6052  // Lock in visible tab
6053  tab_bar->VisibleTabId = tab_bar->SelectedTabId;
6054  tab_bar->VisibleTabWasSubmitted = false;
6055 
6056  // Update scrolling
6057  if (scroll_track_selected_tab_id)
6058  if (ImGuiTabItem* scroll_track_selected_tab = TabBarFindTabByID(tab_bar, scroll_track_selected_tab_id))
6059  TabBarScrollToTab(tab_bar, scroll_track_selected_tab);
6060  tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
6061  tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
6062  const float scrolling_speed = (tab_bar->PrevFrameVisible + 1 < g.FrameCount) ? FLT_MAX : (g.IO.DeltaTime * g.FontSize * 70.0f);
6063  if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
6064  tab_bar->ScrollingAnim = ImLinearSweep(tab_bar->ScrollingAnim, tab_bar->ScrollingTarget, scrolling_speed);
6065 }
6066 
6067 // Dockables uses Name/ID in the global namespace. Non-dockable items use the ID stack.
6068 static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label)
6069 {
6070  if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
6071  {
6072  ImGuiID id = ImHash(label, 0);
6073  KeepAliveID(id);
6074  return id;
6075  }
6076  else
6077  {
6078  ImGuiWindow* window = GImGui->CurrentWindow;
6079  return window->GetID(label);
6080  }
6081 }
6082 
6084 {
6085  ImGuiContext& g = *GImGui;
6086  return g.FontSize * 20.0f;
6087 }
6088 
6090 {
6091  if (tab_id != 0)
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];
6095  return NULL;
6096 }
6097 
6098 // The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
6100 {
6101  if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
6102  tab_bar->Tabs.erase(tab);
6103  if (tab_bar->VisibleTabId == tab_id) { tab_bar->VisibleTabId = 0; }
6104  if (tab_bar->SelectedTabId == tab_id) { tab_bar->SelectedTabId = 0; }
6105  if (tab_bar->NextSelectedTabId == tab_id) { tab_bar->NextSelectedTabId = 0; }
6106 }
6107 
6108 // Called on manual closure attempt
6110 {
6111  if ((tab_bar->VisibleTabId == tab->ID) && !(tab->Flags & ImGuiTabItemFlags_UnsavedDocument))
6112  {
6113  // This will remove a frame of lag for selecting another tab on closure.
6114  // However we don't run it in the case where the 'Unsaved' flag is set, so user gets a chance to fully undo the closure
6115  tab->LastFrameVisible = -1;
6116  tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = 0;
6117  }
6118  else if ((tab_bar->VisibleTabId != tab->ID) && (tab->Flags & ImGuiTabItemFlags_UnsavedDocument))
6119  {
6120  // Actually select before expecting closure
6121  tab_bar->NextSelectedTabId = tab->ID;
6122  }
6123 }
6124 
6125 static float ImGui::TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling)
6126 {
6127  scrolling = ImMin(scrolling, tab_bar->OffsetMax - tab_bar->BarRect.GetWidth());
6128  return ImMax(scrolling, 0.0f);
6129 }
6130 
6132 {
6133  ImGuiContext& g = *GImGui;
6134  float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
6135  int order = tab_bar->GetTabOrder(tab);
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);
6138  if (tab_bar->ScrollingTarget > tab_x1)
6139  tab_bar->ScrollingTarget = tab_x1;
6140  if (tab_bar->ScrollingTarget + tab_bar->BarRect.GetWidth() < tab_x2)
6141  tab_bar->ScrollingTarget = tab_x2 - tab_bar->BarRect.GetWidth();
6142 }
6143 
6144 void ImGui::TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir)
6145 {
6146  IM_ASSERT(dir == -1 || dir == +1);
6147  IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
6148  tab_bar->ReorderRequestTabId = tab->ID;
6149  tab_bar->ReorderRequestDir = dir;
6150 }
6151 
6153 {
6154  ImGuiContext& g = *GImGui;
6155  ImGuiWindow* window = g.CurrentWindow;
6156 
6157  const ImVec2 arrow_button_size(g.FontSize - 2.0f, g.FontSize + g.Style.FramePadding.y * 2.0f);
6158  const float scrolling_buttons_width = arrow_button_size.x * 2.0f;
6159 
6160  const ImVec2 backup_cursor_pos = window->DC.CursorPos;
6161  //window->DrawList->AddRect(ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width, tab_bar->BarRect.Min.y), ImVec2(tab_bar->BarRect.Max.x, tab_bar->BarRect.Max.y), IM_COL32(255,0,0,255));
6162 
6163  const ImRect avail_bar_rect = tab_bar->BarRect;
6164  bool want_clip_rect = !avail_bar_rect.Contains(ImRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(scrolling_buttons_width, 0.0f)));
6165  if (want_clip_rect)
6166  PushClipRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max + ImVec2(g.Style.ItemInnerSpacing.x, 0.0f), true);
6167 
6168  ImGuiTabItem* tab_to_select = NULL;
6169 
6170  int select_dir = 0;
6171  ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text];
6172  arrow_col.w *= 0.5f;
6173 
6174  PushStyleColor(ImGuiCol_Text, arrow_col);
6175  PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
6176  const float backup_repeat_delay = g.IO.KeyRepeatDelay;
6177  const float backup_repeat_rate = g.IO.KeyRepeatRate;
6178  g.IO.KeyRepeatDelay = 0.250f;
6179  g.IO.KeyRepeatRate = 0.200f;
6180  window->DC.CursorPos = ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width, tab_bar->BarRect.Min.y);
6182  select_dir = -1;
6183  window->DC.CursorPos = ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width + arrow_button_size.x, tab_bar->BarRect.Min.y);
6185  select_dir = +1;
6186  PopStyleColor(2);
6187  g.IO.KeyRepeatRate = backup_repeat_rate;
6188  g.IO.KeyRepeatDelay = backup_repeat_delay;
6189 
6190  if (want_clip_rect)
6191  PopClipRect();
6192 
6193  if (select_dir != 0)
6194  if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
6195  {
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]; // If we are at the end of the list, still scroll to make our tab visible
6199  }
6200  window->DC.CursorPos = backup_cursor_pos;
6201  tab_bar->BarRect.Max.x -= scrolling_buttons_width + 1.0f;
6202 
6203  return tab_to_select;
6204 }
6205 
6206 //-------------------------------------------------------------------------
6207 // [SECTION] Widgets: BeginTabItem, EndTabItem, etc.
6208 //-------------------------------------------------------------------------
6209 // [BETA API] API may evolve! This code has been extracted out of the Docking branch,
6210 // and some of the construct which are not used in Master may be left here to facilitate merging.
6211 //-------------------------------------------------------------------------
6212 // - BeginTabItem()
6213 // - EndTabItem()
6214 // - TabItemEx() [Internal]
6215 // - SetTabItemClosed()
6216 // - TabItemCalcSize() [Internal]
6217 // - TabItemRenderBackground() [Internal]
6218 // - TabItemLabelAndCloseButton() [Internal]
6219 //-------------------------------------------------------------------------
6220 
6221 bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags)
6222 {
6223  ImGuiContext& g = *GImGui;
6224  if (g.CurrentWindow->SkipItems)
6225  return false;
6226 
6227  IM_ASSERT(g.CurrentTabBar.Size > 0 && "Needs to be called between BeginTabBar() and EndTabBar()!");
6228  ImGuiTabBar* tab_bar = g.CurrentTabBar.back();
6229  bool ret = TabItemEx(tab_bar, label, p_open, flags);
6230  if (ret && !(flags & ImGuiTabItemFlags_NoPushId))
6231  {
6232  ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
6233  g.CurrentWindow->IDStack.push_back(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label)
6234  }
6235  return ret;
6236 }
6237 
6239 {
6240  ImGuiContext& g = *GImGui;
6241  if (g.CurrentWindow->SkipItems)
6242  return;
6243 
6244  IM_ASSERT(g.CurrentTabBar.Size > 0 && "Needs to be called between BeginTabBar() and EndTabBar()!");
6245  ImGuiTabBar* tab_bar = g.CurrentTabBar.back();
6246  IM_ASSERT(tab_bar->LastTabItemIdx >= 0 && "Needs to be called between BeginTabItem() and EndTabItem()");
6247  ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
6248  if (!(tab->Flags & ImGuiTabItemFlags_NoPushId))
6250 }
6251 
6252 bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags)
6253 {
6254  // Layout whole tab bar if not already done
6255  if (tab_bar->WantLayout)
6256  TabBarLayout(tab_bar);
6257 
6258  ImGuiContext& g = *GImGui;
6259  ImGuiWindow* window = g.CurrentWindow;
6260  if (window->SkipItems)
6261  return false;
6262 
6263  const ImGuiStyle& style = g.Style;
6264  const ImGuiID id = TabBarCalcTabID(tab_bar, label);
6265 
6266  // If the user called us with *p_open == false, we early out and don't render. We make a dummy call to ItemAdd() so that attempts to use a contextual popup menu with an implicit ID won't use an older ID.
6267  if (p_open && !*p_open)
6268  {
6270  ItemAdd(ImRect(), id);
6271  PopItemFlag();
6272  return false;
6273  }
6274 
6275  // Calculate tab contents size
6276  ImVec2 size = TabItemCalcSize(label, p_open != NULL);
6277 
6278  // Acquire tab data
6279  ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, id);
6280  bool tab_is_new = false;
6281  if (tab == NULL)
6282  {
6283  tab_bar->Tabs.push_back(ImGuiTabItem());
6284  tab = &tab_bar->Tabs.back();
6285  tab->ID = id;
6286  tab->Width = size.x;
6287  tab_is_new = true;
6288  }
6289  tab_bar->LastTabItemIdx = (short)tab_bar->Tabs.index_from_ptr(tab);
6290  tab->WidthContents = size.x;
6291 
6292  const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
6293  const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0;
6294  const bool tab_appearing = (tab->LastFrameVisible + 1 < g.FrameCount);
6295  tab->LastFrameVisible = g.FrameCount;
6296  tab->Flags = flags;
6297 
6298  // If we are not reorderable, always reset offset based on submission order.
6299  // (We already handled layout and sizing using the previous known order, but sizing is not affected by order!)
6300  if (!tab_appearing && !(tab_bar->Flags & ImGuiTabBarFlags_Reorderable))
6301  {
6302  tab->Offset = tab_bar->OffsetNextTab;
6303  tab_bar->OffsetNextTab += tab->Width + g.Style.ItemInnerSpacing.x;
6304  }
6305 
6306  // Update selected tab
6307  if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
6308  if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
6309  tab_bar->NextSelectedTabId = id; // New tabs gets activated
6310 
6311  // Lock visibility
6312  bool tab_contents_visible = (tab_bar->VisibleTabId == id);
6313  if (tab_contents_visible)
6314  tab_bar->VisibleTabWasSubmitted = true;
6315 
6316  // On the very first frame of a tab bar we let first tab contents be visible to minimize appearing glitches
6317  if (!tab_contents_visible && tab_bar->SelectedTabId == 0 && tab_bar_appearing)
6318  if (tab_bar->Tabs.Size == 1 && !(tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs))
6319  tab_contents_visible = true;
6320 
6321  if (tab_appearing && !(tab_bar_appearing && !tab_is_new))
6322  {
6324  ItemAdd(ImRect(), id);
6325  PopItemFlag();
6326  return tab_contents_visible;
6327  }
6328 
6329  if (tab_bar->SelectedTabId == id)
6330  tab->LastFrameSelected = g.FrameCount;
6331 
6332  // Backup current layout position
6333  const ImVec2 backup_main_cursor_pos = window->DC.CursorPos;
6334 
6335  // Layout
6336  size.x = tab->Width;
6337  window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2((float)(int)tab->Offset - tab_bar->ScrollingAnim, 0.0f);
6338  ImVec2 pos = window->DC.CursorPos;
6339  ImRect bb(pos, pos + size);
6340 
6341  // We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation)
6342  bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x >= tab_bar->BarRect.Max.x);
6343  if (want_clip_rect)
6344  PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->BarRect.Min.x), bb.Min.y - 1), ImVec2(tab_bar->BarRect.Max.x, bb.Max.y), true);
6345 
6346  ItemSize(bb, style.FramePadding.y);
6347  if (!ItemAdd(bb, id))
6348  {
6349  if (want_clip_rect)
6350  PopClipRect();
6351  window->DC.CursorPos = backup_main_cursor_pos;
6352  return tab_contents_visible;
6353  }
6354 
6355  // Click to Select a tab
6357  if (g.DragDropActive)
6359  bool hovered, held;
6360  bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
6361  hovered |= (g.HoveredId == id);
6362  if (pressed || ((flags & ImGuiTabItemFlags_SetSelected) && !tab_contents_visible)) // SetSelected can only be passed on explicit tab bar
6363  tab_bar->NextSelectedTabId = id;
6364 
6365  // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
6366  if (!held)
6368 
6369  // Drag and drop: re-order tabs
6370  if (held && !tab_appearing && IsMouseDragging(0))
6371  {
6372  if (!g.DragDropActive && (tab_bar->Flags & ImGuiTabBarFlags_Reorderable))
6373  {
6374  // While moving a tab it will jump on the other side of the mouse, so we also test for MouseDelta.x
6375  if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < bb.Min.x)
6376  {
6377  if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
6378  TabBarQueueChangeTabOrder(tab_bar, tab, -1);
6379  }
6380  else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x)
6381  {
6382  if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
6383  TabBarQueueChangeTabOrder(tab_bar, tab, +1);
6384  }
6385  }
6386  }
6387 
6388 #if 0
6389  if (hovered && g.HoveredIdNotActiveTimer > 0.50f && bb.GetWidth() < tab->WidthContents)
6390  {
6391  // Enlarge tab display when hovering
6392  bb.Max.x = bb.Min.x + (float)(int)ImLerp(bb.GetWidth(), tab->WidthContents, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f));
6393  display_draw_list = GetOverlayDrawList(window);
6394  TabItemRenderBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive));
6395  }
6396 #endif
6397 
6398  // Render tab shape
6399  ImDrawList* display_draw_list = window->DrawList;
6400  const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabUnfocused));
6401  TabItemBackground(display_draw_list, bb, flags, tab_col);
6402  RenderNavHighlight(bb, id);
6403 
6404  // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
6405  const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
6406  if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)))
6407  tab_bar->NextSelectedTabId = id;
6408 
6411 
6412  // Render tab label, process close button
6413  const ImGuiID close_button_id = p_open ? window->GetID((void*)(intptr_t)(id + 1)) : 0;
6414  bool just_closed = TabItemLabelAndCloseButton(display_draw_list, bb, flags, label, id, close_button_id);
6415  if (just_closed)
6416  {
6417  *p_open = false;
6418  TabBarCloseTab(tab_bar, tab);
6419  }
6420 
6421  // Restore main window position so user can draw there
6422  if (want_clip_rect)
6423  PopClipRect();
6424  window->DC.CursorPos = backup_main_cursor_pos;
6425 
6426  // Tooltip (FIXME: Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer)
6427  if (g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > 0.50f)
6428  if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip))
6429  SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
6430 
6431  return tab_contents_visible;
6432 }
6433 
6434 // [Public] This is call is 100% optional but it allows to remove some one-frame glitches when a tab has been unexpectedly removed.
6435 // To use it to need to call the function SetTabItemClosed() after BeginTabBar() and before any call to BeginTabItem()
6436 void ImGui::SetTabItemClosed(const char* label)
6437 {
6438  ImGuiContext& g = *GImGui;
6439  bool is_within_manual_tab_bar = (g.CurrentTabBar.Size > 0) && !(g.CurrentTabBar.back()->Flags & ImGuiTabBarFlags_DockNode);
6440  if (is_within_manual_tab_bar)
6441  {
6442  ImGuiTabBar* tab_bar = g.CurrentTabBar.back();
6443  IM_ASSERT(tab_bar->WantLayout); // Needs to be called AFTER BeginTabBar() and BEFORE the first call to BeginTabItem()
6444  ImGuiID tab_id = TabBarCalcTabID(tab_bar, label);
6445  TabBarRemoveTab(tab_bar, tab_id);
6446  }
6447 }
6448 
6449 ImVec2 ImGui::TabItemCalcSize(const char* label, bool has_close_button)
6450 {
6451  ImGuiContext& g = *GImGui;
6452  ImVec2 label_size = CalcTextSize(label, NULL, true);
6453  ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x, label_size.y + g.Style.FramePadding.y * 2.0f);
6454  if (has_close_button)
6455  size.x += g.Style.FramePadding.x + (g.Style.ItemInnerSpacing.x + g.FontSize); // We use Y intentionally to fit the close button circle.
6456  else
6457  size.x += g.Style.FramePadding.x + 1.0f;
6458  return ImVec2(ImMin(size.x, TabBarCalcMaxTabWidth()), size.y);
6459 }
6460 
6461 void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col)
6462 {
6463  // While rendering tabs, we trim 1 pixel off the top of our bounding box so they can fit within a regular frame height while looking "detached" from it.
6464  (void)flags;
6465  ImGuiContext& g = *GImGui;
6466  const float width = bb.GetWidth();
6467  IM_ASSERT(width > 0.0f);
6468  const float rounding = ImMax(0.0f, ImMin(g.Style.TabRounding, width * 0.5f - 1.0f));
6469  float y1 = bb.Min.y + 1.0f;
6470  float y2 = bb.Max.y - 1.0f;
6471  draw_list->PathLineTo(ImVec2(bb.Min.x, y2));
6472  draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9);
6473  draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12);
6474  draw_list->PathLineTo(ImVec2(bb.Max.x, y2));
6475  draw_list->AddConvexPolyFilled(draw_list->_Path.Data, draw_list->_Path.Size, col);
6476  if (g.Style.TabBorderSize > 0.0f)
6477  draw_list->AddPolyline(draw_list->_Path.Data, draw_list->_Path.Size, GetColorU32(ImGuiCol_Border), false, g.Style.TabBorderSize);
6478  draw_list->PathClear();
6479 }
6480 
6481 // Render text label (with custom clipping) + Unsaved Document marker + Close Button logic
6482 bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, const char* label, ImGuiID tab_id, ImGuiID close_button_id)
6483 {
6484  ImGuiContext& g = *GImGui;
6485  ImGuiStyle& style = g.Style;
6486  ImVec2 label_size = CalcTextSize(label, NULL, true);
6487  if (bb.GetWidth() <= 1.0f)
6488  return false;
6489 
6490  // Render text label (with clipping + alpha gradient) + unsaved marker
6491  const char* TAB_UNSAVED_MARKER = "*";
6492  ImRect text_pixel_clip_bb(bb.Min.x + style.FramePadding.x, bb.Min.y + style.FramePadding.y, bb.Max.x - style.FramePadding.x, bb.Max.y);
6494  {
6495  text_pixel_clip_bb.Max.x -= CalcTextSize(TAB_UNSAVED_MARKER, NULL, false).x;
6496  ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + style.FramePadding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + style.FramePadding.y + (float)(int)(-g.FontSize * 0.25f));
6497  RenderTextClippedEx(draw_list, unsaved_marker_pos, bb.Max - style.FramePadding, TAB_UNSAVED_MARKER, NULL, NULL);
6498  }
6499  ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
6500 
6501  // Close Button
6502  // We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap()
6503  // 'hovered' will be true when hovering the Tab but NOT when hovering the close button
6504  // 'g.HoveredId==id' will be true when hovering the Tab including when hovering the close button
6505  // 'g.ActiveId==close_button_id' will be true when we are holding on the close button, in which case both hovered booleans are false
6506  bool close_button_pressed = false;
6507  bool close_button_visible = false;
6508  if (close_button_id != 0)
6509  if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == close_button_id)
6510  close_button_visible = true;
6511  if (close_button_visible)
6512  {
6513  ImGuiItemHoveredDataBackup last_item_backup;
6514  const float close_button_sz = g.FontSize * 0.5f;
6515  if (CloseButton(close_button_id, ImVec2(bb.Max.x - style.FramePadding.x - close_button_sz, bb.Min.y + style.FramePadding.y + close_button_sz), close_button_sz))
6516  close_button_pressed = true;
6517  last_item_backup.Restore();
6518 
6519  // Close with middle mouse button
6521  close_button_pressed = true;
6522 
6523  text_pixel_clip_bb.Max.x -= close_button_sz * 2.0f;
6524  }
6525 
6526  // Label with ellipsis
6527  // FIXME: This should be extracted into a helper but the use of text_pixel_clip_bb and !close_button_visible makes it tricky to abstract at the moment
6528  const char* label_display_end = FindRenderedTextEnd(label);
6529  if (label_size.x > text_ellipsis_clip_bb.GetWidth())
6530  {
6531  const int ellipsis_dot_count = 3;
6532  const float ellipsis_width = (1.0f + 1.0f) * ellipsis_dot_count - 1.0f;
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) // Always display at least 1 character if there's no room for character + ellipsis
6536  {
6537  label_end = label + ImTextCountUtf8BytesFromChar(label, label_display_end);
6538  label_size_clipped_x = g.Font->CalcTextSizeA(g.FontSize, FLT_MAX, 0.0f, label, label_end).x;
6539  }
6540  while (label_end > label && ImCharIsBlankA(label_end[-1])) // Trim trailing space
6541  {
6542  label_end--;
6543  label_size_clipped_x -= g.Font->CalcTextSizeA(g.FontSize, FLT_MAX, 0.0f, label_end, label_end + 1).x; // Ascii blanks are always 1 byte
6544  }
6545  RenderTextClippedEx(draw_list, text_pixel_clip_bb.Min, text_pixel_clip_bb.Max, label, label_end, &label_size, ImVec2(0.0f, 0.0f));
6546 
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)
6549  RenderPixelEllipsis(draw_list, ImVec2(ellipsis_x, text_pixel_clip_bb.Min.y), ellipsis_dot_count, GetColorU32(ImGuiCol_Text));
6550  }
6551  else
6552  {
6553  RenderTextClippedEx(draw_list, text_pixel_clip_bb.Min, text_pixel_clip_bb.Max, label, label_display_end, &label_size, ImVec2(0.0f, 0.0f));
6554  }
6555 
6556  return close_button_pressed;
6557 }
ImGuiGroupData::AdvanceCursor
bool AdvanceCursor
Definition: imgui_internal.h:504
ImGui::InputScalarAsWidgetReplacement
IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect &bb, ImGuiID id, const char *label, ImGuiDataType data_type, void *data_ptr, const char *format)
Definition: imgui_widgets.cpp:2609
ImGuiInputTextCallbackData::SelectionStart
int SelectionStart
Definition: imgui.h:1428
IMGUI_CDECL
#define IMGUI_CDECL
Definition: imgui_internal.h:132
ImGuiTabItem::Offset
float Offset
Definition: imgui_internal.h:1212
ImGuiMouseCursor_ResizeEW
@ ImGuiMouseCursor_ResizeEW
Definition: imgui.h:1128
ImGuiKey_Z
@ ImGuiKey_Z
Definition: imgui.h:922
ImGuiInputTextState::InitialText
ImVector< char > InitialText
Definition: imgui_internal.h:526
ImGuiContext::InputTextState
ImGuiInputTextState InputTextState
Definition: imgui_internal.h:843
ImGuiContext::ActiveIdSource
ImGuiInputSource ActiveIdSource
Definition: imgui_internal.h:759
ImGuiAxis_Y
@ ImGuiAxis_Y
Definition: imgui_internal.h:361
ImGuiMenuColumns::DeclColumns
float DeclColumns(float w0, float w1, float w2)
Definition: imgui_widgets.cpp:5440
ImGuiDataType_Float
@ ImGuiDataType_Float
Definition: imgui.h:883
ImGui::DragBehaviorT
IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T *v, float v_speed, const T v_min, const T v_max, const char *format, float power, ImGuiDragFlags flags)
ImGui::CalcWindowExpectedSize
IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow *window)
Definition: imgui.cpp:4512
ImGuiCond_Once
@ ImGuiCond_Once
Definition: imgui.h:1146
InputTextFilterCharacter
static bool InputTextFilterCharacter(unsigned int *p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void *user_data)
Definition: imgui_widgets.cpp:3058
ImIsPowerOfTwo
static bool ImIsPowerOfTwo(int v)
Definition: imgui_internal.h:149
ImFont::Descent
float Descent
Definition: imgui.h:2088
IMGUI_PAYLOAD_TYPE_COLOR_3F
#define IMGUI_PAYLOAD_TYPE_COLOR_3F
Definition: imgui.h:873
ImGuiMenuColumns::Width
float Width
Definition: imgui_internal.h:512
ImGuiWindow::WindowRounding
float WindowRounding
Definition: imgui_internal.h:1092
ImGui::DragIntRange2
IMGUI_API bool DragIntRange2(const char *label, int *v_current_min, int *v_current_max, float v_speed=1.0f, int v_min=0, int v_max=0, const char *format="%d", const char *format_max=NULL)
Definition: imgui_widgets.cpp:2019
ImGui::ColorPickerOptionsPopup
IMGUI_API void ColorPickerOptionsPopup(const float *ref_col, ImGuiColorEditFlags flags)
Definition: imgui_widgets.cpp:4554
ImGuiCol_TextDisabled
@ ImGuiCol_TextDisabled
Definition: imgui.h:990
ImGui::BeginTabBar
IMGUI_API bool BeginTabBar(const char *str_id, ImGuiTabBarFlags flags=0)
Definition: imgui_widgets.cpp:5825
ImGuiContext::NavMoveRequest
bool NavMoveRequest
Definition: imgui_internal.h:804
ImGuiComboFlags_HeightMask_
@ ImGuiComboFlags_HeightMask_
Definition: imgui.h:797
ImGui::DragInt4
IMGUI_API bool DragInt4(const char *label, int v[4], float v_speed=1.0f, int v_min=0, int v_max=0, const char *format="%d")
Definition: imgui_widgets.cpp:2014
ImGui::PushItemWidth
IMGUI_API void PushItemWidth(float item_width)
Definition: imgui.cpp:5496
ImGui::InputInt3
IMGUI_API bool InputInt3(const char *label, int v[3], ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2797
ImGui::EndDragDropSource
IMGUI_API void EndDragDropSource()
Definition: imgui.cpp:8431
ImGuiCol_TitleBgActive
@ ImGuiCol_TitleBgActive
Definition: imgui.h:1000
ImGui::EndMenuBar
IMGUI_API void EndMenuBar()
Definition: imgui_widgets.cpp:5517
ImGui::SetNextWindowSizeConstraints
IMGUI_API void SetNextWindowSizeConstraints(const ImVec2 &size_min, const ImVec2 &size_max, ImGuiSizeCallback custom_callback=NULL, void *custom_callback_data=NULL)
Definition: imgui.cpp:6062
ImGuiContext::FontBaseSize
float FontBaseSize
Definition: imgui_internal.h:725
ImGui::ListBoxFooter
IMGUI_API void ListBoxFooter()
Definition: imgui_widgets.cpp:5154
ImGui::BeginPopup
IMGUI_API bool BeginPopup(const char *str_id, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:6775
ImGui::RenderColorRectWithAlphaCheckerboard
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding=0.0f, int rounding_corners_flags=~0)
Definition: imgui_widgets.cpp:4038
STB_TEXTEDIT_K_LEFT
#define STB_TEXTEDIT_K_LEFT
Definition: imgui_widgets.cpp:2971
ImGuiInputTextFlags_CallbackResize
@ ImGuiInputTextFlags_CallbackResize
Definition: imgui.h:745
ImGui::TextColored
IMGUI_API void TextColored(const ImVec4 &col, const char *fmt,...) IM_FMTARGS(2)
Definition: imgui_widgets.cpp:245
ImDrawList::AddRectFilledMultiColor
IMGUI_API void AddRectFilledMultiColor(const ImVec2 &a, const ImVec2 &b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left)
Definition: imgui_draw.cpp:1077
ImGuiColorEditFlags_HDR
@ ImGuiColorEditFlags_HDR
Definition: imgui.h:1103
ImGuiContext::FontSize
float FontSize
Definition: imgui_internal.h:724
ImGuiWindow::WindowPadding
ImVec2 WindowPadding
Definition: imgui_internal.h:1091
ImGuiInputTextState::ID
ImGuiID ID
Definition: imgui_internal.h:524
ImGui::PushItemFlag
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled)
Definition: imgui.cpp:5571
ImGui::GetTreeNodeToLabelSpacing
IMGUI_API float GetTreeNodeToLabelSpacing()
Definition: imgui_widgets.cpp:4937
ImPow
static float ImPow(float x, float y)
Definition: imgui_internal.h:203
ImGui::GetFontTexUvWhitePixel
IMGUI_API ImVec2 GetFontTexUvWhitePixel()
Definition: imgui.cpp:6179
ImDrawCornerFlags_TopRight
@ ImDrawCornerFlags_TopRight
Definition: imgui.h:1764
ImGuiPlotArrayGetterData::Stride
int Stride
Definition: imgui_widgets.cpp:5331
ImGui::ClosePopupToLevel
IMGUI_API void ClosePopupToLevel(int remaining, bool apply_focus_to_window_under)
Definition: imgui.cpp:6712
ImGuiIO::KeySuper
bool KeySuper
Definition: imgui.h:1348
ImGuiWindowFlags_NoScrollbar
@ ImGuiWindowFlags_NoScrollbar
Definition: imgui.h:689
ImGuiListClipper
Definition: imgui.h:1651
ImGui::CollapseButton
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2 &pos)
Definition: imgui_widgets.cpp:680
ImGui::DragFloat
IMGUI_API bool DragFloat(const char *label, float *v, float v_speed=1.0f, float v_min=0.0f, float v_max=0.0f, const char *format="%.3f", float power=1.0f)
Definition: imgui_widgets.cpp:1954
ImGui::InputScalarN
IMGUI_API bool InputScalarN(const char *label, ImGuiDataType data_type, void *v, int components, const void *step=NULL, const void *step_fast=NULL, const char *format=NULL, ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2701
ImGuiMenuColumns::CalcExtraSpace
float CalcExtraSpace(float avail_w)
Definition: imgui_widgets.cpp:5451
ImGuiIO::KeyCtrl
bool KeyCtrl
Definition: imgui.h:1345
ImGuiPlotArrayGetterData::ImGuiPlotArrayGetterData
ImGuiPlotArrayGetterData(const float *values, int stride)
Definition: imgui_widgets.cpp:5333
ImGuiTabBar::SelectedTabId
ImGuiID SelectedTabId
Definition: imgui_internal.h:1224
ImGui::LabelTextV
IMGUI_API void LabelTextV(const char *label, const char *fmt, va_list args) IM_FMTLIST(2)
Definition: imgui_widgets.cpp:302
ImGui::TextColoredV
IMGUI_API void TextColoredV(const ImVec4 &col, const char *fmt, va_list args) IM_FMTLIST(2)
Definition: imgui_widgets.cpp:253
ImGuiComboFlags_HeightSmall
@ ImGuiComboFlags_HeightSmall
Definition: imgui.h:791
DataTypeFormatString
static int DataTypeFormatString(char *buf, int buf_size, ImGuiDataType data_type, const void *data_ptr, const char *format)
Definition: imgui_widgets.cpp:1525
ImGui::RenderArrow
IMGUI_API void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale=1.0f)
Definition: imgui.cpp:2338
ImGuiInputTextFlags_NoHorizontalScroll
@ ImGuiInputTextFlags_NoHorizontalScroll
Definition: imgui.h:739
ImGuiContext::DragDropPayload
ImGuiPayload DragDropPayload
Definition: imgui_internal.h:826
ImGuiTabBar::ID
ImGuiID ID
Definition: imgui_internal.h:1223
ImGuiColorEditFlags_NoInputs
@ ImGuiColorEditFlags_NoInputs
Definition: imgui.h:1093
ImGuiColorEditFlags_NoDragDrop
@ ImGuiColorEditFlags_NoDragDrop
Definition: imgui.h:1097
ImGuiKey
int ImGuiKey
Definition: imgui.h:124
ImGuiSliderFlags_None
@ ImGuiSliderFlags_None
Definition: imgui_internal.h:296
ImGuiInputTextState::CursorAnim
float CursorAnim
Definition: imgui_internal.h:532
IM_COL32_R_SHIFT
#define IM_COL32_R_SHIFT
Definition: imgui.h:1676
ImGuiStb
Definition: imgui_internal.h:93
ImGui::ColorConvertRGBtoHSV
IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float &out_h, float &out_s, float &out_v)
Definition: imgui.cpp:1735
ImGuiInputSource_Mouse
@ ImGuiInputSource_Mouse
Definition: imgui_internal.h:373
ImGuiDir
int ImGuiDir
Definition: imgui.h:123
ImGuiWindow::MenuBarRect
ImRect MenuBarRect() const
Definition: imgui_internal.h:1177
ImGuiContext::ActiveIdIsJustActivated
bool ActiveIdIsJustActivated
Definition: imgui_internal.h:750
ImGuiNavLayer_Main
@ ImGuiNavLayer_Main
Definition: imgui_internal.h:428
ImGui::GetID
IMGUI_API ImGuiID GetID(const char *str_id)
Definition: imgui.cpp:6378
ImGuiButtonFlags_AlignTextBaseLine
@ ImGuiButtonFlags_AlignTextBaseLine
Definition: imgui_internal.h:287
ImFont::FontSize
float FontSize
Definition: imgui.h:2074
ImClamp
static T ImClamp(T v, T mn, T mx)
Definition: imgui_internal.h:218
ImGuiInputTextFlags_CharsHexadecimal
@ ImGuiInputTextFlags_CharsHexadecimal
Definition: imgui.h:728
NULL
#define NULL
ImPool::GetOrAddByKey
T * GetOrAddByKey(ImGuiID key)
Definition: imgui_internal.h:254
ImGuiNavLayer_Menu
@ ImGuiNavLayer_Menu
Definition: imgui_internal.h:429
IM_STATIC_ASSERT
IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo)==ImGuiDataType_COUNT)
ImGuiWindowTempData::ItemFlags
ImGuiItemFlags ItemFlags
Definition: imgui_internal.h:1033
ImGuiWindow::FocusIdxAllRequestCurrent
int FocusIdxAllRequestCurrent
Definition: imgui_internal.h:1156
STB_TEXTEDIT_K_UNDO
#define STB_TEXTEDIT_K_UNDO
Definition: imgui_widgets.cpp:2981
ImGui::RadioButton
IMGUI_API bool RadioButton(const char *label, bool active)
Definition: imgui_widgets.cpp:944
ImRect::Expand
void Expand(const float amount)
Definition: imgui_internal.h:464
ImDrawList::PrimReserve
IMGUI_API void PrimReserve(int idx_count, int vtx_count)
Definition: imgui_draw.cpp:600
ImTextStrToUtf8
int ImTextStrToUtf8(char *buf, int buf_size, const ImWchar *in_text, const ImWchar *in_text_end)
Definition: imgui.cpp:1678
ImGuiInputTextState::UserCallback
ImGuiInputTextCallback UserCallback
Definition: imgui_internal.h:538
ImGui::ProgressBar
IMGUI_API void ProgressBar(float fraction, const ImVec2 &size_arg=ImVec2(-1, 0), const char *overlay=NULL)
Definition: imgui_widgets.cpp:1013
ImGui::SliderInt2
IMGUI_API bool SliderInt2(const char *label, int v[2], int v_min, int v_max, const char *format="%d")
Definition: imgui_widgets.cpp:2429
ImGui::EndTabBar
IMGUI_API void EndTabBar()
Definition: imgui_widgets.cpp:5887
ImGui::SliderScalarN
IMGUI_API bool SliderScalarN(const char *label, ImGuiDataType data_type, void *v, int components, const void *v_min, const void *v_max, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:2366
ImGuiContext::HoveredIdNotActiveTimer
float HoveredIdNotActiveTimer
Definition: imgui_internal.h:745
ImGuiInputTextFlags_CharsDecimal
@ ImGuiInputTextFlags_CharsDecimal
Definition: imgui.h:727
ImGui::RenderArrowPointingAt
IMGUI_API void RenderArrowPointingAt(ImDrawList *draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col)
Definition: imgui_draw.cpp:2885
ImGuiContext::NavActivateDownId
ImGuiID NavActivateDownId
Definition: imgui_internal.h:777
ImGuiButtonFlags_NoNavFocus
@ ImGuiButtonFlags_NoNavFocus
Definition: imgui_internal.h:291
ImGuiContext::Font
ImFont * Font
Definition: imgui_internal.h:723
ImU64
unsigned long long ImU64
Definition: imgui.h:160
ImGui::GetTextLineHeightWithSpacing
IMGUI_API float GetTextLineHeightWithSpacing()
Definition: imgui.cpp:6145
ImGui::OpenPopupOnItemClick
IMGUI_API bool OpenPopupOnItemClick(const char *str_id=NULL, int mouse_button=1)
Definition: imgui.cpp:6662
StbTexteditRow::baseline_y_delta
float baseline_y_delta
Definition: imstb_textedit.h:363
ImDrawList::PathClear
void PathClear()
Definition: imgui.h:1840
ImGuiContext::HoveredIdPreviousFrame
ImGuiID HoveredIdPreviousFrame
Definition: imgui_internal.h:743
ImGuiNavDirSourceFlags_Keyboard
@ ImGuiNavDirSourceFlags_Keyboard
Definition: imgui_internal.h:403
ImGuiContext::Style
ImGuiStyle Style
Definition: imgui_internal.h:722
ImGuiStb::STB_TEXTEDIT_MOVEWORDLEFT_IMPL
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui_widgets.cpp:2914
ImRotate
static ImVec2 ImRotate(const ImVec2 &v, float cos_a, float sin_a)
Definition: imgui_internal.h:235
ImGui::PushStyleColor
IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col)
Definition: imgui.cpp:5624
ImGuiCol_Separator
@ ImGuiCol_Separator
Definition: imgui.h:1016
ImGui::LabelText
IMGUI_API void LabelText(const char *label, const char *fmt,...) IM_FMTARGS(2)
Definition: imgui_widgets.cpp:293
ImGui::CalcItemSize
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y)
Definition: imgui.cpp:2861
ImGuiComboFlags_NoPreview
@ ImGuiComboFlags_NoPreview
Definition: imgui.h:796
ImGuiContext::DragDropActive
bool DragDropActive
Definition: imgui_internal.h:821
ImGuiCond
int ImGuiCond
Definition: imgui.h:121
ImGuiCol_SliderGrab
@ ImGuiCol_SliderGrab
Definition: imgui.h:1008
ImGui::RenderCheckMark
IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col, float sz)
Definition: imgui.cpp:2379
ImGuiCol_PlotHistogram
@ ImGuiCol_PlotHistogram
Definition: imgui.h:1029
ImGui::PushColumnClipRect
IMGUI_API void PushColumnClipRect(int column_index=-1)
Definition: imgui.cpp:8142
ImVec4::z
float z
Definition: imgui.h:178
ImGuiPlotType_Histogram
@ ImGuiPlotType_Histogram
Definition: imgui_internal.h:367
ImGuiContext::PlatformImePos
ImVec2 PlatformImePos
Definition: imgui_internal.h:856
ImGui::SetNextWindowPos
IMGUI_API void SetNextWindowPos(const ImVec2 &pos, ImGuiCond cond=0, const ImVec2 &pivot=ImVec2(0, 0))
Definition: imgui.cpp:6045
ImGuiWindow::Flags
ImGuiWindowFlags Flags
Definition: imgui_internal.h:1084
ImGuiIO::KeyShift
bool KeyShift
Definition: imgui.h:1346
ImGuiCol_HeaderHovered
@ ImGuiCol_HeaderHovered
Definition: imgui.h:1014
ImRect::Min
ImVec2 Min
Definition: imgui_internal.h:443
ImDrawList::AddCircle
IMGUI_API void AddCircle(const ImVec2 &centre, float radius, ImU32 col, int num_segments=12, float thickness=1.0f)
Definition: imgui_draw.cpp:1138
ImGui::GetCursorScreenPos
IMGUI_API ImVec2 GetCursorScreenPos()
Definition: imgui.cpp:6239
ImGui::FindWindowByName
IMGUI_API ImGuiWindow * FindWindowByName(const char *name)
Definition: imgui.cpp:4387
ImGuiIO::MouseDownDuration
float MouseDownDuration[5]
Definition: imgui.h:1387
IMGUI_PAYLOAD_TYPE_COLOR_4F
#define IMGUI_PAYLOAD_TYPE_COLOR_4F
Definition: imgui.h:874
ImGuiTabBar::LastTabItemIdx
short LastTabItemIdx
Definition: imgui_internal.h:1240
ImGui::GetClipboardText
const IMGUI_API char * GetClipboardText()
Definition: imgui.cpp:2903
ImGuiWindowTempData::CurrentLineSize
ImVec2 CurrentLineSize
Definition: imgui_internal.h:1008
DataTypeApplyOpFromText
static bool DataTypeApplyOpFromText(const char *buf, const char *initial_value_buf, ImGuiDataType data_type, void *data_ptr, const char *format)
Definition: imgui_widgets.cpp:1576
ImGuiNavInput_TweakSlow
@ ImGuiNavInput_TweakSlow
Definition: imgui.h:947
ImGui::BeginMenu
IMGUI_API bool BeginMenu(const char *label, bool enabled=true)
Definition: imgui_widgets.cpp:5557
ImVector::index_from_ptr
int index_from_ptr(const T *it) const
Definition: imgui.h:1214
ImGuiItemHoveredDataBackup
Definition: imgui_internal.h:1181
IM_COL32_BLACK_TRANS
#define IM_COL32_BLACK_TRANS
Definition: imgui.h:1685
ImGuiWindow::NavLastIds
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]
Definition: imgui_internal.h:1149
ImGuiInputSource_Nav
@ ImGuiInputSource_Nav
Definition: imgui_internal.h:374
ImGuiInputTextCallbackData::EventKey
ImGuiKey EventKey
Definition: imgui.h:1422
ImGuiInputTextFlags_Multiline
@ ImGuiInputTextFlags_Multiline
Definition: imgui.h:747
ImGuiCol_TextSelectedBg
@ ImGuiCol_TextSelectedBg
Definition: imgui.h:1031
ImGui::Button
IMGUI_API bool Button(const char *label, const ImVec2 &size=ImVec2(0, 0))
Definition: imgui_widgets.cpp:575
ImGui::TabBarCalcMaxTabWidth
static float TabBarCalcMaxTabWidth()
Definition: imgui_widgets.cpp:6083
ImGuiTabBar::NextSelectedTabId
ImGuiID NextSelectedTabId
Definition: imgui_internal.h:1225
ImGui::MarkItemEdited
IMGUI_API void MarkItemEdited(ImGuiID id)
Definition: imgui.cpp:2646
ImGui::IsItemActive
IMGUI_API bool IsItemActive()
Definition: imgui.cpp:4135
ImGui::ColorPicker4
IMGUI_API bool ColorPicker4(const char *label, float col[4], ImGuiColorEditFlags flags=0, const float *ref_col=NULL)
Definition: imgui_widgets.cpp:4083
ImGuiContext::ActiveId
ImGuiID ActiveId
Definition: imgui_internal.h:746
ImGuiNavInput_TweakFast
@ ImGuiNavInput_TweakFast
Definition: imgui.h:948
ImGuiWindowFlags
int ImGuiWindowFlags
Definition: imgui.h:144
ImGuiButtonFlags_PressedOnClick
@ ImGuiButtonFlags_PressedOnClick
Definition: imgui_internal.h:280
s
XmlRpcServer s
ImFont::ContainerAtlas
ImFontAtlas * ContainerAtlas
Definition: imgui.h:2087
ImGuiContext::FrameCount
int FrameCount
Definition: imgui_internal.h:729
ImGuiSeparatorFlags
int ImGuiSeparatorFlags
Definition: imgui_internal.h:85
ImGuiTabBar::PrevFrameVisible
int PrevFrameVisible
Definition: imgui_internal.h:1228
ImGuiWindowTempData::NavLayerActiveMaskNext
int NavLayerActiveMaskNext
Definition: imgui_internal.h:1022
ImCos
static float ImCos(float x)
Definition: imgui_internal.h:207
ImGuiColorEditFlags__DataTypeMask
@ ImGuiColorEditFlags__DataTypeMask
Definition: imgui.h:1114
ImFormatString
int ImFormatString(char *buf, size_t buf_size, const char *fmt,...)
Definition: imgui.cpp:1387
ImGuiNextWindowData::SizeConstraintCond
ImGuiCond SizeConstraintCond
Definition: imgui_internal.h:672
ImGui::IsMouseClicked
IMGUI_API bool IsMouseClicked(int button, bool repeat=false)
Definition: imgui.cpp:4026
ImGuiNavInput_Activate
@ ImGuiNavInput_Activate
Definition: imgui.h:933
ImGuiButtonFlags_Disabled
@ ImGuiButtonFlags_Disabled
Definition: imgui_internal.h:286
ImGuiTabBarFlags
int ImGuiTabBarFlags
Definition: imgui.h:141
ImGuiDataTypeInfo::Size
size_t Size
Definition: imgui_widgets.cpp:1480
ImGuiWindow::SizeContents
ImVec2 SizeContents
Definition: imgui_internal.h:1089
ImGuiPayload::SourceId
ImGuiID SourceId
Definition: imgui.h:1457
IM_COL32_B_SHIFT
#define IM_COL32_B_SHIFT
Definition: imgui.h:1678
ImGui::SetColorEditOptions
IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags)
Definition: imgui_widgets.cpp:4466
ImGuiTabBar::ReorderRequestDir
int ReorderRequestDir
Definition: imgui_internal.h:1237
ImGuiStb::STB_TEXTEDIT_INSERTCHARS
static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING *obj, int pos, const ImWchar *new_text, int new_text_len)
Definition: imgui_widgets.cpp:2939
ImGuiWindowTempData::NavLayerCurrent
ImGuiNavLayer NavLayerCurrent
Definition: imgui_internal.h:1019
ImGui::PopStyleColor
IMGUI_API void PopStyleColor(int count=1)
Definition: imgui.cpp:5644
ImGuiNextWindowData::MenuBarOffsetMinVal
ImVec2 MenuBarOffsetMinVal
Definition: imgui_internal.h:684
ImGui::ItemHoverable
IMGUI_API bool ItemHoverable(const ImRect &bb, ImGuiID id)
Definition: imgui.cpp:2797
ImGuiContext::DragSpeedDefaultRatio
float DragSpeedDefaultRatio
Definition: imgui_internal.h:850
GDataTypeInfo
static const ImGuiDataTypeInfo GDataTypeInfo[]
Definition: imgui_widgets.cpp:1485
ImGuiKey_Enter
@ ImGuiKey_Enter
Definition: imgui.h:915
ImGuiIO::KeyRepeatRate
float KeyRepeatRate
Definition: imgui.h:1287
ImGuiInputTextCallbackData::EventFlag
ImGuiInputTextFlags EventFlag
Definition: imgui.h:1414
ImDrawCornerFlags_TopLeft
@ ImDrawCornerFlags_TopLeft
Definition: imgui.h:1763
ImGuiInputTextState::CursorFollow
bool CursorFollow
Definition: imgui_internal.h:533
ImGuiKey_Delete
@ ImGuiKey_Delete
Definition: imgui.h:912
ImGuiTabBarFlags_AutoSelectNewTabs
@ ImGuiTabBarFlags_AutoSelectNewTabs
Definition: imgui.h:805
ImGuiPlotArrayGetterData
Definition: imgui_widgets.cpp:5328
ImGuiStb::is_word_boundary_from_right
static int is_word_boundary_from_right(STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui_widgets.cpp:2913
ImGuiInputTextCallbackData::CursorPos
int CursorPos
Definition: imgui.h:1427
ImGuiWindowTempData::LastItemDisplayRect
ImRect LastItemDisplayRect
Definition: imgui_internal.h:1018
ImGuiInputTextFlags_CallbackHistory
@ ImGuiInputTextFlags_CallbackHistory
Definition: imgui.h:734
ImGuiContext::ActiveIdPreviousFrame
ImGuiID ActiveIdPreviousFrame
Definition: imgui_internal.h:747
STB_TEXTEDIT_K_WORDRIGHT
#define STB_TEXTEDIT_K_WORDRIGHT
Definition: imgui_widgets.cpp:2984
ImGuiStb::STB_TEXTEDIT_STRINGLEN
static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING *obj)
Definition: imgui_widgets.cpp:2894
ImGuiKey_X
@ ImGuiKey_X
Definition: imgui.h:920
ImGuiStb::STB_TEXTEDIT_NEWLINE
static ImWchar STB_TEXTEDIT_NEWLINE
Definition: imgui_widgets.cpp:2898
ImVec1::x
float x
Definition: imgui_internal.h:270
ImGuiContext::NavWindow
ImGuiWindow * NavWindow
Definition: imgui_internal.h:774
ImGui::ListBoxHeader
IMGUI_API bool ListBoxHeader(const char *label, const ImVec2 &size=ImVec2(0, 0))
Definition: imgui_widgets.cpp:5109
ImGui::Dummy
IMGUI_API void Dummy(const ImVec2 &size)
Definition: imgui_widgets.cpp:1090
ImGui::LogText
IMGUI_API void LogText(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui.cpp:8617
ImGuiInputTextState::CursorAnimReset
void CursorAnimReset()
Definition: imgui_internal.h:542
ImGuiTabBarFlags_DockNode
@ ImGuiTabBarFlags_DockNode
Definition: imgui_internal.h:1199
ImFloor
static float ImFloor(float f)
Definition: imgui_internal.h:232
ImGuiContext::NextWindowData
ImGuiNextWindowData NextWindowData
Definition: imgui_internal.h:769
ImGuiWindow::ParentWindow
ImGuiWindow * ParentWindow
Definition: imgui_internal.h:1143
ImGui::IsMouseDragging
IMGUI_API bool IsMouseDragging(int button=0, float lock_threshold=-1.0f)
Definition: imgui.cpp:4058
ImDrawList
Definition: imgui.h:1787
ImGuiColorEditFlags_NoSidePreview
@ ImGuiColorEditFlags_NoSidePreview
Definition: imgui.h:1096
ImGuiDataType_S32
@ ImGuiDataType_S32
Definition: imgui.h:879
ImGuiColorEditFlags__OptionsDefault
@ ImGuiColorEditFlags__OptionsDefault
Definition: imgui.h:1116
ImGuiContext::InputTextPasswordFont
ImFont InputTextPasswordFont
Definition: imgui_internal.h:844
ImGuiInputTextFlags_CharsScientific
@ ImGuiInputTextFlags_CharsScientific
Definition: imgui.h:744
ImTextureID
void * ImTextureID
Definition: imgui.h:111
ImGuiInputTextState::UserCallbackData
void * UserCallbackData
Definition: imgui_internal.h:539
ImGuiKey_RightArrow
@ ImGuiKey_RightArrow
Definition: imgui.h:904
ImGui::CalcTypematicPressedRepeatAmount
IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate)
Definition: imgui.cpp:3970
ImGui::IsMouseHoveringRect
IMGUI_API bool IsMouseHoveringRect(const ImVec2 &r_min, const ImVec2 &r_max, bool clip=true)
Definition: imgui.cpp:3940
ImGuiContext::HoveredIdTimer
float HoveredIdTimer
Definition: imgui_internal.h:744
ImGuiInputTextState::OnKeyPressed
void OnKeyPressed(int key)
Definition: imgui_widgets.cpp:2992
STB_TEXTEDIT_GETWIDTH_NEWLINE
#define STB_TEXTEDIT_GETWIDTH_NEWLINE
Definition: imgui_internal.h:100
ImGuiColorEditFlags_AlphaPreview
@ ImGuiColorEditFlags_AlphaPreview
Definition: imgui.h:1101
ImRect::GetSize
ImVec2 GetSize() const
Definition: imgui_internal.h:452
ImDrawCornerFlags_All
@ ImDrawCornerFlags_All
Definition: imgui.h:1771
ImTriangleClosestPoint
ImVec2 ImTriangleClosestPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p)
Definition: imgui.cpp:1248
ImGuiWindow::Collapsed
bool Collapsed
Definition: imgui_internal.h:1105
ImGuiInputReadMode_Repeat
@ ImGuiInputReadMode_Repeat
Definition: imgui_internal.h:386
imgui.h
ImGui::DragFloatRange2
IMGUI_API bool DragFloatRange2(const char *label, float *v_current_min, float *v_current_max, float v_speed=1.0f, float v_min=0.0f, float v_max=0.0f, const char *format="%.3f", const char *format_max=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:1974
ImFont::IndexAdvanceX
ImVector< float > IndexAdvanceX
Definition: imgui.h:2078
ImGuiAxis_X
@ ImGuiAxis_X
Definition: imgui_internal.h:360
ImGui::PushFont
IMGUI_API void PushFont(ImFont *font)
Definition: imgui.cpp:5553
ImGuiWindowTempData::StateStorage
ImGuiStorage * StateStorage
Definition: imgui_internal.h:1028
ImGuiInputTextState::ScrollX
float ScrollX
Definition: imgui_internal.h:530
ImGuiTabBarFlags_FittingPolicyScroll
@ ImGuiTabBarFlags_FittingPolicyScroll
Definition: imgui.h:811
ImGuiStb::STB_TEXTEDIT_GETWIDTH
static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING *obj, int line_start_idx, int char_idx)
Definition: imgui_widgets.cpp:2896
ImGui::Unindent
IMGUI_API void Unindent(float indent_w=0.0f)
Definition: imgui.cpp:6507
ImGui::Text
IMGUI_API void Text(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui_widgets.cpp:226
ImGui::InvisibleButton
IMGUI_API bool InvisibleButton(const char *str_id, const ImVec2 &size)
Definition: imgui_widgets.cpp:593
ImGuiWindowFlags_Popup
@ ImGuiWindowFlags_Popup
Definition: imgui.h:714
ImGuiCol_Button
@ ImGuiCol_Button
Definition: imgui.h:1010
ImGuiColorEditFlags_NoPicker
@ ImGuiColorEditFlags_NoPicker
Definition: imgui.h:1090
ImGuiID
unsigned int ImGuiID
Definition: imgui.h:118
ImGuiTabBarFlags_SaveSettings
@ ImGuiTabBarFlags_SaveSettings
Definition: imgui_internal.h:1202
ImFont::IndexLookup
ImVector< ImWchar > IndexLookup
Definition: imgui.h:2079
ImGui::GetWindowContentRegionMax
IMGUI_API ImVec2 GetWindowContentRegionMax()
Definition: imgui.cpp:6127
ImGuiCol_ScrollbarGrabHovered
@ ImGuiCol_ScrollbarGrabHovered
Definition: imgui.h:1005
ImGui::TabBarFindTabByID
IMGUI_API ImGuiTabItem * TabBarFindTabByID(ImGuiTabBar *tab_bar, ImGuiID tab_id)
Definition: imgui_widgets.cpp:6089
ImGuiColumnsSet::LineMinY
float LineMinY
Definition: imgui_internal.h:605
STB_TEXTEDIT_K_LINEEND
#define STB_TEXTEDIT_K_LINEEND
Definition: imgui_widgets.cpp:2976
ImTextCountUtf8BytesFromStr
int ImTextCountUtf8BytesFromStr(const ImWchar *in_text, const ImWchar *in_text_end)
Definition: imgui.cpp:1694
ImGui::NavMoveRequestCancel
IMGUI_API void NavMoveRequestCancel()
Definition: imgui.cpp:7216
ImGuiIO::MouseDragMaxDistanceSqr
float MouseDragMaxDistanceSqr[5]
Definition: imgui.h:1390
ImVector< ImGuiTabBarSortItem >
ImGui::Selectable
IMGUI_API bool Selectable(const char *label, bool selected=false, ImGuiSelectableFlags flags=0, const ImVec2 &size=ImVec2(0, 0))
Definition: imgui_widgets.cpp:4997
ImGuiWindowFlags_AlwaysAutoResize
@ ImGuiWindowFlags_AlwaysAutoResize
Definition: imgui.h:692
ImFontGlyph
Definition: imgui.h:1927
ImGuiTabBar
Definition: imgui_internal.h:1220
StbTexteditRow::ymin
float ymin
Definition: imstb_textedit.h:364
IM_COL32_G_SHIFT
#define IM_COL32_G_SHIFT
Definition: imgui.h:1677
ImGuiStyleVar_ItemSpacing
@ ImGuiStyleVar_ItemSpacing
Definition: imgui.h:1068
ImGui::SmallButton
IMGUI_API bool SmallButton(const char *label)
Definition: imgui_widgets.cpp:581
ImGuiCol_Header
@ ImGuiCol_Header
Definition: imgui.h:1013
ImGui::TabBarCalcTabID
static ImU32 TabBarCalcTabID(ImGuiTabBar *tab_bar, const char *label)
Definition: imgui_widgets.cpp:6068
ImGuiInputTextCallbackData::BufTextLen
int BufTextLen
Definition: imgui.h:1424
ImGui::DragInt3
IMGUI_API bool DragInt3(const char *label, int v[3], float v_speed=1.0f, int v_min=0, int v_max=0, const char *format="%d")
Definition: imgui_widgets.cpp:2009
ImGui::ClearActiveID
IMGUI_API void ClearActiveID()
Definition: imgui.cpp:2617
ImGuiStb::is_separator
static bool is_separator(unsigned int c)
Definition: imgui_widgets.cpp:2912
ImGuiContext::NavDisableMouseHover
bool NavDisableMouseHover
Definition: imgui_internal.h:797
ImGuiContext::NavId
ImGuiID NavId
Definition: imgui_internal.h:775
ImGui::RenderText
IMGUI_API void RenderText(ImVec2 pos, const char *text, const char *text_end=NULL, bool hide_text_after_hash=true)
Definition: imgui.cpp:2224
ImGuiSliderFlags
int ImGuiSliderFlags
Definition: imgui_internal.h:86
ImGui::DragBehavior
IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void *v, float v_speed, const void *v_min, const void *v_max, const char *format, float power, ImGuiDragFlags flags)
Definition: imgui_widgets.cpp:1821
ImGui::SetNextTreeNodeOpen
IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiCond cond=0)
Definition: imgui_widgets.cpp:4943
ImGui::SliderBehaviorT
IMGUI_API bool SliderBehaviorT(const ImRect &bb, ImGuiID id, ImGuiDataType data_type, T *v, const T v_min, const T v_max, const char *format, float power, ImGuiSliderFlags flags, ImRect *out_grab_bb)
ImVec2
Definition: imgui.h:164
ImGuiKey_End
@ ImGuiKey_End
Definition: imgui.h:910
ImGuiIO::KeyAlt
bool KeyAlt
Definition: imgui.h:1347
ImDrawList::PathArcToFast
IMGUI_API void PathArcToFast(const ImVec2 &centre, float radius, int a_min_of_12, int a_max_of_12)
Definition: imgui_draw.cpp:935
ImGuiTabItem::WidthContents
float WidthContents
Definition: imgui_internal.h:1214
ImGui::VSliderFloat
IMGUI_API bool VSliderFloat(const char *label, const ImVec2 &size, float *v, float v_min, float v_max, const char *format="%.3f", float power=1.0f)
Definition: imgui_widgets.cpp:2504
ImGuiContext::TabBars
ImPool< ImGuiTabBar > TabBars
Definition: imgui_internal.h:838
ImGuiTabBarSortItem::Width
float Width
Definition: imgui_internal.h:708
ImTriangleContainsPoint
bool ImTriangleContainsPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p)
Definition: imgui.cpp:1229
ImGui::RenderTextClipped
IMGUI_API void RenderTextClipped(const ImVec2 &pos_min, const ImVec2 &pos_max, const char *text, const char *text_end, const ImVec2 *text_size_if_known, const ImVec2 &align=ImVec2(0, 0), const ImRect *clip_rect=NULL)
Definition: imgui.cpp:2296
ImGuiTabBar::ContentsHeight
float ContentsHeight
Definition: imgui_internal.h:1230
ImGuiContext::NavDisableHighlight
bool NavDisableHighlight
Definition: imgui_internal.h:796
STB_TEXTEDIT_K_REDO
#define STB_TEXTEDIT_K_REDO
Definition: imgui_widgets.cpp:2982
ImRect::Max
ImVec2 Max
Definition: imgui_internal.h:444
ImGuiWindowFlags_MenuBar
@ ImGuiWindowFlags_MenuBar
Definition: imgui.h:696
ImGuiPopupPositionPolicy_ComboBox
@ ImGuiPopupPositionPolicy_ComboBox
Definition: imgui_internal.h:436
ImGuiWindowTempData::CursorPos
ImVec2 CursorPos
Definition: imgui_internal.h:1004
ImGuiCol_HeaderActive
@ ImGuiCol_HeaderActive
Definition: imgui.h:1015
ImGui::TabItemCalcSize
IMGUI_API ImVec2 TabItemCalcSize(const char *label, bool has_close_button)
Definition: imgui_widgets.cpp:6449
Plot_ArrayGetter
static float Plot_ArrayGetter(void *data, int idx)
Definition: imgui_widgets.cpp:5336
ImGuiWindow::FocusIdxAllCounter
int FocusIdxAllCounter
Definition: imgui_internal.h:1154
ImFont::FindGlyph
const IMGUI_API ImFontGlyph * FindGlyph(ImWchar c) const
Definition: imgui_draw.cpp:2433
ImGui::RenderNavHighlight
IMGUI_API void RenderNavHighlight(const ImRect &bb, ImGuiID id, ImGuiNavHighlightFlags flags=ImGuiNavHighlightFlags_TypeDefault)
Definition: imgui.cpp:2397
ImGui::InputTextMultiline
IMGUI_API bool InputTextMultiline(const char *label, char *buf, size_t buf_size, const ImVec2 &size=ImVec2(0, 0), ImGuiInputTextFlags flags=0, ImGuiInputTextCallback callback=NULL, void *user_data=NULL)
Definition: imgui_widgets.cpp:2827
ImGuiButtonFlags_PressedOnRelease
@ ImGuiButtonFlags_PressedOnRelease
Definition: imgui_internal.h:281
ImGui::PushTextWrapPos
IMGUI_API void PushTextWrapPos(float wrap_local_pos_x=0.0f)
Definition: imgui.cpp:5609
ImGuiWindowTempData::ColumnsSet
ImGuiColumnsSet * ColumnsSet
Definition: imgui_internal.h:1045
step
unsigned int step
ImRect::Overlaps
bool Overlaps(const ImRect &r) const
Definition: imgui_internal.h:461
ImGuiWindowFlags_NoSavedSettings
@ ImGuiWindowFlags_NoSavedSettings
Definition: imgui.h:694
IM_S32_MIN
static const ImS32 IM_S32_MIN
Definition: imgui_widgets.cpp:69
ImGuiTreeNodeFlags_Framed
@ ImGuiTreeNodeFlags_Framed
Definition: imgui.h:755
ImS32
signed int ImS32
Definition: imgui.h:149
ImGui::BeginDragDropSource
IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags=0)
Definition: imgui.cpp:8333
ImGuiIO::KeyRepeatDelay
float KeyRepeatDelay
Definition: imgui.h:1286
ImGuiContext::LogAutoExpandMaxDepth
int LogAutoExpandMaxDepth
Definition: imgui_internal.h:870
ImGuiButtonFlags
int ImGuiButtonFlags
Definition: imgui_internal.h:79
ImGuiComboFlags_PopupAlignLeft
@ ImGuiComboFlags_PopupAlignLeft
Definition: imgui.h:790
ImGuiWindow::SizeFull
ImVec2 SizeFull
Definition: imgui_internal.h:1087
ImTextStrFromUtf8
int ImTextStrFromUtf8(ImWchar *buf, int buf_size, const char *in_text, const char *in_text_end, const char **in_text_remaining)
Definition: imgui.cpp:1590
ImGui::PlotEx
IMGUI_API void 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)
Definition: imgui_widgets.cpp:5218
ImGuiWindowTempData::GroupStack
ImVector< ImGuiGroupData > GroupStack
Definition: imgui_internal.h:1039
ImGui::CheckboxFlags
IMGUI_API bool CheckboxFlags(const char *label, unsigned int *flags, unsigned int flags_value)
Definition: imgui_widgets.cpp:929
ImGuiInputTextState::CurLenW
int CurLenW
Definition: imgui_internal.h:528
ImMin
static T ImMin(T lhs, T rhs)
Definition: imgui_internal.h:216
ImGuiWindowFlags_ChildMenu
@ ImGuiWindowFlags_ChildMenu
Definition: imgui.h:716
ImGui::BulletTextV
IMGUI_API void BulletTextV(const char *fmt, va_list args) IM_FMTLIST(1)
Definition: imgui_widgets.cpp:336
ImGui::SplitterBehavior
IMGUI_API bool SplitterBehavior(const ImRect &bb, ImGuiID id, ImGuiAxis axis, float *size1, float *size2, float min_size1, float min_size2, float hover_extend=0.0f, float hover_visibility_delay=0.0f)
Definition: imgui_widgets.cpp:1195
ImGuiTabBar::Tabs
ImVector< ImGuiTabItem > Tabs
Definition: imgui_internal.h:1222
StbTexteditRow::num_chars
int num_chars
Definition: imstb_textedit.h:365
ImGuiTabBarFlags_FittingPolicyResizeDown
@ ImGuiTabBarFlags_FittingPolicyResizeDown
Definition: imgui.h:810
ImGuiColorEditFlags_NoTooltip
@ ImGuiColorEditFlags_NoTooltip
Definition: imgui.h:1094
ImGuiInputTextState
Definition: imgui_internal.h:522
ImDrawList::AddRect
IMGUI_API void AddRect(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding=0.0f, int rounding_corners_flags=ImDrawCornerFlags_All, float thickness=1.0f)
Definition: imgui_draw.cpp:1050
ImGui::EndCombo
IMGUI_API void EndCombo()
Definition: imgui_widgets.cpp:1370
ImGui::GetCurrentWindow
ImGuiWindow * GetCurrentWindow()
Definition: imgui_internal.h:1258
ImGuiHoveredFlags_AllowWhenBlockedByPopup
@ ImGuiHoveredFlags_AllowWhenBlockedByPopup
Definition: imgui.h:845
ImGuiTreeNodeFlags
int ImGuiTreeNodeFlags
Definition: imgui.h:143
ImGui::TreeNodeV
IMGUI_API bool TreeNodeV(const char *str_id, const char *fmt, va_list args) IM_FMTLIST(2)
Definition: imgui_widgets.cpp:4634
imgui_internal.h
ImGuiStyle::ItemSpacing
ImVec2 ItemSpacing
Definition: imgui.h:1239
ImGuiColorEditFlags_HSV
@ ImGuiColorEditFlags_HSV
Definition: imgui.h:1105
ImHash
ImU32 ImHash(const void *data, int data_size, ImU32 seed)
Definition: imgui.cpp:1425
ImDrawList::AddText
IMGUI_API void AddText(const ImVec2 &pos, ImU32 col, const char *text_begin, const char *text_end=NULL)
Definition: imgui_draw.cpp:1197
ImGui::InputInt2
IMGUI_API bool InputInt2(const char *label, int v[2], ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2792
ImGui::ColorEdit4
IMGUI_API bool ColorEdit4(const char *label, float col[4], ImGuiColorEditFlags flags=0)
Definition: imgui_widgets.cpp:3814
ImGuiInputTextFlags_CharsNoBlank
@ ImGuiInputTextFlags_CharsNoBlank
Definition: imgui.h:730
ImGuiColorEditFlags
int ImGuiColorEditFlags
Definition: imgui.h:132
ImDrawList::AddLine
IMGUI_API void AddLine(const ImVec2 &a, const ImVec2 &b, ImU32 col, float thickness=1.0f)
Definition: imgui_draw.cpp:1040
ImGuiTabBarFlags_NoCloseWithMiddleMouseButton
@ ImGuiTabBarFlags_NoCloseWithMiddleMouseButton
Definition: imgui.h:806
ImGuiInputTextFlags_Password
@ ImGuiInputTextFlags_Password
Definition: imgui.h:742
ImGuiTabBarFlags_None
@ ImGuiTabBarFlags_None
Definition: imgui.h:803
ImGui::SliderFloat2
IMGUI_API bool SliderFloat2(const char *label, float v[2], float v_min, float v_max, const char *format="%.3f", float power=1.0f)
Definition: imgui_widgets.cpp:2399
StbTexteditRow::x0
float x0
Definition: imstb_textedit.h:362
ImGuiStyle::FrameRounding
float FrameRounding
Definition: imgui.h:1237
ImGuiCol_ScrollbarGrab
@ ImGuiCol_ScrollbarGrab
Definition: imgui.h:1004
ImGuiInputTextState::BufCapacityA
int BufCapacityA
Definition: imgui_internal.h:529
ImGui::TextDisabledV
IMGUI_API void TextDisabledV(const char *fmt, va_list args) IM_FMTLIST(1)
Definition: imgui_widgets.cpp:268
ImGuiKey_A
@ ImGuiKey_A
Definition: imgui.h:917
ImGuiKey_Home
@ ImGuiKey_Home
Definition: imgui.h:909
ImDrawList::AddPolyline
IMGUI_API void AddPolyline(const ImVec2 *points, const int num_points, ImU32 col, bool closed, float thickness)
Definition: imgui_draw.cpp:666
ImGui::IsPopupOpen
IMGUI_API bool IsPopupOpen(const char *str_id)
Definition: imgui.cpp:6594
ImGuiItemFlags_NoNavDefaultFocus
@ ImGuiItemFlags_NoNavDefaultFocus
Definition: imgui_internal.h:995
ImGuiCol_PlotLinesHovered
@ ImGuiCol_PlotLinesHovered
Definition: imgui.h:1028
ImGuiInputReadMode_RepeatFast
@ ImGuiInputReadMode_RepeatFast
Definition: imgui_internal.h:388
ImGui::IsItemHovered
IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags=0)
Definition: imgui.cpp:2757
ImDrawList::_Path
ImVector< ImVec2 > _Path
Definition: imgui.h:1803
ImGuiInputTextFlags_CallbackCompletion
@ ImGuiInputTextFlags_CallbackCompletion
Definition: imgui.h:733
ImGuiWindowTempData::LastItemStatusFlags
ImGuiItemStatusFlags LastItemStatusFlags
Definition: imgui_internal.h:1016
ImGui::Separator
IMGUI_API void Separator()
Definition: imgui_widgets.cpp:1129
f
f
IM_U32_MAX
static const ImU32 IM_U32_MAX
Definition: imgui_widgets.cpp:72
ImGui::ArrowButtonEx
IMGUI_API bool ArrowButtonEx(const char *str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags)
Definition: imgui_widgets.cpp:615
ImGuiKey_COUNT
@ ImGuiKey_COUNT
Definition: imgui.h:923
ImGui::CalcWrapWidthForPos
IMGUI_API float CalcWrapWidthForPos(const ImVec2 &pos, float wrap_pos_x)
Definition: imgui.cpp:2874
ImGuiCol_FrameBgActive
@ ImGuiCol_FrameBgActive
Definition: imgui.h:998
ImGuiDataTypeInfo
Definition: imgui_widgets.cpp:1478
ImSaturate
static float ImSaturate(float f)
Definition: imgui_internal.h:228
ImGuiTabBar::VisibleTabWasSubmitted
bool VisibleTabWasSubmitted
Definition: imgui_internal.h:1239
ImGuiPayload
Definition: imgui.h:1450
ImRect::Translate
void Translate(const ImVec2 &d)
Definition: imgui_internal.h:466
ImGuiSelectableFlags_SpanAllColumns
@ ImGuiSelectableFlags_SpanAllColumns
Definition: imgui.h:781
ImGui::BeginGroup
IMGUI_API void BeginGroup()
Definition: imgui.cpp:6406
ImTextCountUtf8BytesFromChar
int ImTextCountUtf8BytesFromChar(const char *in_text, const char *in_text_end)
Definition: imgui.cpp:1663
ImGuiContext::NextTreeNodeOpenVal
bool NextTreeNodeOpenVal
Definition: imgui_internal.h:770
ImGui::BeginCombo
IMGUI_API bool BeginCombo(const char *label, const char *preview_value, ImGuiComboFlags flags=0)
Definition: imgui_widgets.cpp:1268
ImGui::FindBestWindowPosForPopupEx
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2 &ref_pos, const ImVec2 &size, ImGuiDir *last_dir, const ImRect &r_outer, const ImRect &r_avoid, ImGuiPopupPositionPolicy policy=ImGuiPopupPositionPolicy_Default)
Definition: imgui.cpp:6873
ImGuiWindow::SkipItems
bool SkipItems
Definition: imgui_internal.h:1107
StbTexteditRow::x1
float x1
Definition: imstb_textedit.h:362
ImGuiIO::MouseDown
bool MouseDown[5]
Definition: imgui.h:1342
ImGuiComboFlags_HeightRegular
@ ImGuiComboFlags_HeightRegular
Definition: imgui.h:792
ImGuiContext::IO
ImGuiIO IO
Definition: imgui_internal.h:721
ImGui::End
IMGUI_API void End()
Definition: imgui.cpp:5371
ImGuiContext::ActiveIdAllowOverlap
bool ActiveIdAllowOverlap
Definition: imgui_internal.h:751
ImGui::IsClippedEx
IMGUI_API bool IsClippedEx(const ImRect &bb, ImGuiID id, bool clip_even_when_logged)
Definition: imgui.cpp:2819
ImCharIsBlankW
static bool ImCharIsBlankW(unsigned int c)
Definition: imgui_internal.h:148
ImVec4::y
float y
Definition: imgui.h:178
ImGuiStyle::ItemInnerSpacing
ImVec2 ItemInnerSpacing
Definition: imgui.h:1240
imstb_textedit.h
ImGuiIO::ConfigInputTextCursorBlink
bool ConfigInputTextCursorBlink
Definition: imgui.h:1301
ImGui::PlotHistogram
IMGUI_API void PlotHistogram(const char *label, const float *values, int values_count, int values_offset=0, const char *overlay_text=NULL, float scale_min=FLT_MAX, float scale_max=FLT_MAX, ImVec2 graph_size=ImVec2(0, 0), int stride=sizeof(float))
Definition: imgui_widgets.cpp:5354
ImGui::Combo
IMGUI_API bool Combo(const char *label, int *current_item, const char *const items[], int items_count, int popup_max_height_in_items=-1)
Definition: imgui_widgets.cpp:1447
ImGuiNextWindowData::SizeConstraintRect
ImRect SizeConstraintRect
Definition: imgui_internal.h:680
ImGui::IsMouseReleased
IMGUI_API bool IsMouseReleased(int button)
Definition: imgui.cpp:4044
ImGuiInputTextState::SelectAll
void SelectAll()
Definition: imgui_internal.h:546
ImGuiContext::NextTreeNodeOpenCond
ImGuiCond NextTreeNodeOpenCond
Definition: imgui_internal.h:771
ImRect::GetBR
ImVec2 GetBR() const
Definition: imgui_internal.h:458
ImGuiInputTextFlags_CallbackAlways
@ ImGuiInputTextFlags_CallbackAlways
Definition: imgui.h:735
ImGui::DragScalarN
IMGUI_API bool DragScalarN(const char *label, ImGuiDataType data_type, void *v, int components, float v_speed, const void *v_min=NULL, const void *v_max=NULL, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:1926
GImGui
ImGuiContext * GImGui
Definition: imgui.cpp:1042
ImGuiInputTextCallback
int(* ImGuiInputTextCallback)(ImGuiInputTextCallbackData *data)
Definition: imgui.h:145
ImS64
signed long long ImS64
Definition: imgui.h:159
ImGuiWindowTempData::TextWrapPos
float TextWrapPos
Definition: imgui_internal.h:1035
IMGUI_TEST_ENGINE_ITEM_INFO
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID, _LABEL, _FLAGS)
Definition: imgui_internal.h:1457
ImGuiDataType_Double
@ ImGuiDataType_Double
Definition: imgui.h:884
ImGuiTabBar::Flags
ImGuiTabBarFlags Flags
Definition: imgui_internal.h:1235
ImGuiColorEditFlags_Uint8
@ ImGuiColorEditFlags_Uint8
Definition: imgui.h:1107
ImGuiInputTextState::StbState
ImGuiStb::STB_TexteditState StbState
Definition: imgui_internal.h:531
ImGuiTabItemFlags_NoCloseWithMiddleMouseButton
@ ImGuiTabItemFlags_NoCloseWithMiddleMouseButton
Definition: imgui.h:822
ImGuiInputTextState::CursorClamp
void CursorClamp()
Definition: imgui_internal.h:543
ImGui::ColorConvertHSVtoRGB
IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float &out_r, float &out_g, float &out_b)
Definition: imgui.cpp:1757
ImGuiIO::MouseClicked
bool MouseClicked[5]
Definition: imgui.h:1383
ImGuiSelectableFlags_PressedOnClick
@ ImGuiSelectableFlags_PressedOnClick
Definition: imgui_internal.h:321
simple-obstacle-avoidance.args
args
Definition: simple-obstacle-avoidance.py:38
ImGuiTabBar::ImGuiTabBar
ImGuiTabBar()
Definition: imgui_widgets.cpp:5795
ImGuiWindow::Scroll
ImVec2 Scroll
Definition: imgui_internal.h:1097
IM_S32_MAX
static const ImS32 IM_S32_MAX
Definition: imgui_widgets.cpp:70
ImVector::Data
T * Data
Definition: imgui.h:1170
ImGuiContext::NavJustMovedToId
ImGuiID NavJustMovedToId
Definition: imgui_internal.h:781
IM_COL32_A_MASK
#define IM_COL32_A_MASK
Definition: imgui.h:1680
ImGui::ShadeVertsLinearColorGradientKeepAlpha
IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList *draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1)
Definition: imgui_draw.cpp:1301
ImGui::SetItemAllowOverlap
IMGUI_API void SetItemAllowOverlap()
Definition: imgui.cpp:4202
ImGuiButtonFlags_Repeat
@ ImGuiButtonFlags_Repeat
Definition: imgui_internal.h:278
ImGuiWindow::TitleBarHeight
float TitleBarHeight() const
Definition: imgui_internal.h:1174
ImStrbolW
const ImWchar * ImStrbolW(const ImWchar *buf_mid_line, const ImWchar *buf_begin)
Definition: imgui.cpp:1327
IM_U64_MAX
static const ImU64 IM_U64_MAX
Definition: imgui_widgets.cpp:84
ImGuiWindowTempData::TreeDepth
int TreeDepth
Definition: imgui_internal.h:1013
ImGuiCol_TabActive
@ ImGuiCol_TabActive
Definition: imgui.h:1024
ImGui::SetItemDefaultFocus
IMGUI_API void SetItemDefaultFocus()
Definition: imgui.cpp:6318
ImGuiButtonFlags_NoKeyModifiers
@ ImGuiButtonFlags_NoKeyModifiers
Definition: imgui_internal.h:288
ImGuiIO::ConfigMacOSXBehaviors
bool ConfigMacOSXBehaviors
Definition: imgui.h:1300
ImGuiNavDirSourceFlags_PadDPad
@ ImGuiNavDirSourceFlags_PadDPad
Definition: imgui_internal.h:404
ImFont::Scale
float Scale
Definition: imgui.h:2075
ImGuiDataType
int ImGuiDataType
Definition: imgui.h:122
ImGuiStb::STB_TEXTEDIT_GETCHAR
static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui_widgets.cpp:2895
ImGuiContext::HoveredRootWindow
ImGuiWindow * HoveredRootWindow
Definition: imgui_internal.h:740
TabBarSortItemComparer
static int IMGUI_CDECL TabBarSortItemComparer(const void *lhs, const void *rhs)
Definition: imgui_widgets.cpp:5816
ImGui::SliderScalar
IMGUI_API bool SliderScalar(const char *label, ImGuiDataType data_type, void *v, const void *v_min, const void *v_max, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:2286
ImGuiItemFlags
int ImGuiItemFlags
Definition: imgui_internal.h:80
InputTextCalcTextSizeW
static ImVec2 InputTextCalcTextSizeW(const ImWchar *text_begin, const ImWchar *text_end, const ImWchar **remaining=NULL, ImVec2 *out_offset=NULL, bool stop_on_new_line=false)
Definition: imgui_widgets.cpp:2846
ImVector::erase
T * erase(const T *it)
Definition: imgui.h:1209
ImGui::ButtonEx
IMGUI_API bool ButtonEx(const char *label, const ImVec2 &size_arg=ImVec2(0, 0), ImGuiButtonFlags flags=0)
Definition: imgui_widgets.cpp:534
ImGuiStyleVar_WindowMinSize
@ ImGuiStyleVar_WindowMinSize
Definition: imgui.h:1059
ImGuiDataTypeInfo::ScanFmt
const char * ScanFmt
Definition: imgui_widgets.cpp:1482
ImGuiButtonFlags_PressedOnDragDropHold
@ ImGuiButtonFlags_PressedOnDragDropHold
Definition: imgui_internal.h:290
ImGuiInputTextState::HasSelection
bool HasSelection() const
Definition: imgui_internal.h:544
ImGuiIO::MouseReleased
bool MouseReleased[5]
Definition: imgui.h:1385
ImGuiTabItem::Width
float Width
Definition: imgui_internal.h:1213
void
typedef void(GLAD_API_PTR *GLDEBUGPROC)(GLenum source
ImGui::TreeNodeEx
IMGUI_API bool TreeNodeEx(const char *label, ImGuiTreeNodeFlags flags=0)
Definition: imgui_widgets.cpp:4644
ImGuiKey_Y
@ ImGuiKey_Y
Definition: imgui.h:921
ImGuiKey_DownArrow
@ ImGuiKey_DownArrow
Definition: imgui.h:906
ImGuiIO::MouseDownDurationPrev
float MouseDownDurationPrev[5]
Definition: imgui.h:1388
ImGuiColorEditFlags_AlphaBar
@ ImGuiColorEditFlags_AlphaBar
Definition: imgui.h:1100
ImGui::FocusPreviousWindowIgnoringOne
IMGUI_API void FocusPreviousWindowIgnoringOne(ImGuiWindow *ignore_window)
Definition: imgui.cpp:5479
ImGuiInputTextFlags_ReadOnly
@ ImGuiInputTextFlags_ReadOnly
Definition: imgui.h:741
ImGui::SetFocusID
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow *window)
Definition: imgui.cpp:2595
ImGuiColorEditFlags__InputsMask
@ ImGuiColorEditFlags__InputsMask
Definition: imgui.h:1113
ImGuiWindow::DrawList
ImDrawList * DrawList
Definition: imgui_internal.h:1141
ImParseFormatPrecision
int ImParseFormatPrecision(const char *fmt, int default_precision)
Definition: imgui_widgets.cpp:2585
ImGuiItemHoveredDataBackup::Restore
void Restore() const
Definition: imgui_internal.h:1190
ImGuiButtonFlags_PressedOnClickRelease
@ ImGuiButtonFlags_PressedOnClickRelease
Definition: imgui_internal.h:279
ImVector::Size
int Size
Definition: imgui.h:1168
ImStrncpy
void ImStrncpy(char *dst, const char *src, size_t count)
Definition: imgui.cpp:1278
ImVec2::x
float x
Definition: imgui.h:166
ImGuiTabBar::OffsetMax
float OffsetMax
Definition: imgui_internal.h:1231
ImGui::ItemAdd
IMGUI_API bool ItemAdd(const ImRect &bb, ImGuiID id, const ImRect *nav_bb=NULL)
Definition: imgui.cpp:2714
ImParseFormatFindStart
const char * ImParseFormatFindStart(const char *fmt)
Definition: imgui_widgets.cpp:2536
ImGui::TreePushRawID
IMGUI_API void TreePushRawID(ImGuiID id)
Definition: imgui_widgets.cpp:4903
ImGuiStyle
Definition: imgui.h:1224
ImGuiInputTextCallbackData::UserData
void * UserData
Definition: imgui.h:1416
ImGuiDir_Up
@ ImGuiDir_Up
Definition: imgui.h:894
ImTriangleBarycentricCoords
void ImTriangleBarycentricCoords(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p, float &out_u, float &out_v, float &out_w)
Definition: imgui.cpp:1237
ImGuiDataType_U32
@ ImGuiDataType_U32
Definition: imgui.h:880
ImGuiDragDropFlags_SourceNoDisableHover
@ ImGuiDragDropFlags_SourceNoDisableHover
Definition: imgui.h:860
ImGui::GetWindowAllowedExtentRect
IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow *window)
Definition: imgui.cpp:6863
ImGui::PopItemFlag
IMGUI_API void PopItemFlag()
Definition: imgui.cpp:5581
ImRect::Add
void Add(const ImVec2 &p)
Definition: imgui_internal.h:462
ImVector::push_back
void push_back(const T &v)
Definition: imgui.h:1206
ImGuiCol_SeparatorActive
@ ImGuiCol_SeparatorActive
Definition: imgui.h:1018
ImGuiContext::ActiveIdWindow
ImGuiWindow * ActiveIdWindow
Definition: imgui_internal.h:757
ImGuiIO::MouseDelta
ImVec2 MouseDelta
Definition: imgui.h:1374
ImGuiContext::DragDropSourceFlags
ImGuiDragDropFlags DragDropSourceFlags
Definition: imgui_internal.h:823
ImGuiTreeNodeFlags_FramePadding
@ ImGuiTreeNodeFlags_FramePadding
Definition: imgui.h:764
ImGuiWindow::ScrollbarSizes
ImVec2 ScrollbarSizes
Definition: imgui_internal.h:1100
ImGui::MemAlloc
IMGUI_API void * MemAlloc(size_t size)
Definition: imgui.cpp:2888
RenderArrowsForVerticalBar
static void RenderArrowsForVerticalBar(ImDrawList *draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w)
Definition: imgui_widgets.cpp:4073
ImDrawList::AddTriangle
IMGUI_API void AddTriangle(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, ImU32 col, float thickness=1.0f)
Definition: imgui_draw.cpp:1116
ImWchar
unsigned short ImWchar
Definition: imgui.h:119
IM_U64_MIN
static const ImU64 IM_U64_MIN
Definition: imgui_widgets.cpp:80
ImDrawList::AddImage
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2 &a, const ImVec2 &b, const ImVec2 &uv_a=ImVec2(0, 0), const ImVec2 &uv_b=ImVec2(1, 1), ImU32 col=0xFFFFFFFF)
Definition: imgui_draw.cpp:1202
ImGui::TextDisabled
IMGUI_API void TextDisabled(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui_widgets.cpp:260
ImGui::LogRenderedText
IMGUI_API void LogRenderedText(const ImVec2 *ref_pos, const char *text, const char *text_end=NULL)
Definition: imgui.cpp:8634
ImGuiWindowTempData::NavLayerCurrentMask
int NavLayerCurrentMask
Definition: imgui_internal.h:1020
ImGuiInputTextCallbackData::BufDirty
bool BufDirty
Definition: imgui.h:1426
ImGui::PushID
IMGUI_API void PushID(const char *str_id)
Definition: imgui.cpp:6347
ImGuiSelectableFlags_DontClosePopups
@ ImGuiSelectableFlags_DontClosePopups
Definition: imgui.h:780
ImGui::InputScalar
IMGUI_API bool InputScalar(const char *label, ImGuiDataType data_type, void *v, const void *step=NULL, const void *step_fast=NULL, const char *format=NULL, ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2638
ImGui::CalcItemWidth
IMGUI_API float CalcItemWidth()
Definition: imgui.cpp:5524
ImGuiLayoutType_Vertical
@ ImGuiLayoutType_Vertical
Definition: imgui_internal.h:353
ImGui::InputFloat4
IMGUI_API bool InputFloat4(const char *label, float v[4], const char *format="%.3f", ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2745
ImGui::SetTooltip
IMGUI_API void SetTooltip(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui.cpp:6576
ImGui::SliderFloat
IMGUI_API bool SliderFloat(const char *label, float *v, float v_min, float v_max, const char *format="%.3f", float power=1.0f)
Definition: imgui_widgets.cpp:2394
ImGui::DragInt2
IMGUI_API bool DragInt2(const char *label, int v[2], float v_speed=1.0f, int v_min=0, int v_max=0, const char *format="%d")
Definition: imgui_widgets.cpp:2004
ImGuiStorage::GetInt
IMGUI_API int GetInt(ImGuiID key, int default_val=0) const
Definition: imgui.cpp:1861
ImGuiInputTextFlags_EnterReturnsTrue
@ ImGuiInputTextFlags_EnterReturnsTrue
Definition: imgui.h:732
ImGuiContext::ScrollbarClickDeltaToGrabCenter
ImVec2 ScrollbarClickDeltaToGrabCenter
Definition: imgui_internal.h:851
id
GLenum GLuint id
Definition: gl.h:1033
Items_ArrayGetter
static bool Items_ArrayGetter(void *data, int idx, const char **out_text)
Definition: imgui_widgets.cpp:1376
ImGuiContext::NavInputSource
ImGuiInputSource NavInputSource
Definition: imgui_internal.h:783
ImGui::TreePop
IMGUI_API void TreePop()
Definition: imgui_widgets.cpp:4911
ImGuiCol_Text
@ ImGuiCol_Text
Definition: imgui.h:989
ImGuiWindow::InnerClipRect
ImRect InnerClipRect
Definition: imgui_internal.h:1131
ImGui::GetNavInputAmount2d
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor=0.0f, float fast_factor=0.0f)
Definition: imgui.cpp:7371
ImGuiStyle::DisplaySafeAreaPadding
ImVec2 DisplaySafeAreaPadding
Definition: imgui.h:1252
IM_S64_MAX
static const ImS64 IM_S64_MAX
Definition: imgui_widgets.cpp:78
ImGuiTabBarFlags_IsFocused
@ ImGuiTabBarFlags_IsFocused
Definition: imgui_internal.h:1201
ImGuiIO::MouseClickedPos
ImVec2 MouseClickedPos[5]
Definition: imgui.h:1381
ImGuiNavForward_None
@ ImGuiNavForward_None
Definition: imgui_internal.h:421
ImGuiTabBar::ScrollingTarget
float ScrollingTarget
Definition: imgui_internal.h:1234
ImGuiContext::NavIdIsAlive
bool NavIdIsAlive
Definition: imgui_internal.h:794
ImGui::EndGroup
IMGUI_API void EndGroup()
Definition: imgui.cpp:6431
ImGui::SliderFloat3
IMGUI_API bool SliderFloat3(const char *label, float v[3], float v_min, float v_max, const char *format="%.3f", float power=1.0f)
Definition: imgui_widgets.cpp:2404
ImGui::BeginTabItem
IMGUI_API bool BeginTabItem(const char *label, bool *p_open=NULL, ImGuiTabItemFlags flags=0)
Definition: imgui_widgets.cpp:6221
ImGuiWindowTempData::LayoutType
ImGuiLayoutType LayoutType
Definition: imgui_internal.h:1029
ImLinearSweep
static float ImLinearSweep(float current, float target, float speed)
Definition: imgui_internal.h:236
ImGui::PopID
IMGUI_API void PopID()
Definition: imgui.cpp:6372
ImGuiCol_ButtonHovered
@ ImGuiCol_ButtonHovered
Definition: imgui.h:1011
ImTextCountCharsFromUtf8
int ImTextCountCharsFromUtf8(const char *in_text, const char *in_text_end)
Definition: imgui.cpp:1609
ImGuiKey_LeftArrow
@ ImGuiKey_LeftArrow
Definition: imgui.h:903
ImGui::Spacing
IMGUI_API void Spacing()
Definition: imgui_widgets.cpp:1082
CalcMaxPopupHeightFromItemCount
static float CalcMaxPopupHeightFromItemCount(int items_count)
Definition: imgui_widgets.cpp:1260
ImGuiInputSource_NavKeyboard
@ ImGuiInputSource_NavKeyboard
Definition: imgui_internal.h:375
IM_ARRAYSIZE
#define IM_ARRAYSIZE(_ARR)
Definition: imgui.h:73
STB_TEXTEDIT_K_LINESTART
#define STB_TEXTEDIT_K_LINESTART
Definition: imgui_widgets.cpp:2975
ImGuiCol_TabUnfocused
@ ImGuiCol_TabUnfocused
Definition: imgui.h:1025
ImGui::TreeNode
IMGUI_API bool TreeNode(const char *label)
Definition: imgui_widgets.cpp:4626
ImGuiDataType_COUNT
@ ImGuiDataType_COUNT
Definition: imgui.h:885
ImGui::SetHoveredID
IMGUI_API void SetHoveredID(ImGuiID id)
Definition: imgui.cpp:2622
ImGui::BeginPopupEx
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
Definition: imgui.cpp:6753
ImGui::BeginDragDropTarget
IMGUI_API bool BeginDragDropTarget()
Definition: imgui.cpp:8516
ImGuiInputTextFlags_AutoSelectAll
@ ImGuiInputTextFlags_AutoSelectAll
Definition: imgui.h:731
ImGuiMenuColumns::Pos
float Pos[4]
Definition: imgui_internal.h:513
ImGuiTabBar::GetTabOrder
int GetTabOrder(const ImGuiTabItem *tab) const
Definition: imgui_internal.h:1243
ImGuiTreeNodeFlags_AllowItemOverlap
@ ImGuiTreeNodeFlags_AllowItemOverlap
Definition: imgui.h:756
ImGuiColorEditFlags_PickerHueBar
@ ImGuiColorEditFlags_PickerHueBar
Definition: imgui.h:1109
ImGuiWindowTempData::TreeDepthMayJumpToParentOnPop
ImU32 TreeDepthMayJumpToParentOnPop
Definition: imgui_internal.h:1014
ImGui::InputInt4
IMGUI_API bool InputInt4(const char *label, int v[4], ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2802
STB_TEXTEDIT_K_DELETE
#define STB_TEXTEDIT_K_DELETE
Definition: imgui_widgets.cpp:2979
ImVector::reserve
void reserve(int new_capacity)
Definition: imgui.h:1203
ImGui::SetNavID
IMGUI_API void SetNavID(ImGuiID id, int nav_layer)
Definition: imgui.cpp:2550
ImGui::FindRenderedTextEnd
const IMGUI_API char * FindRenderedTextEnd(const char *text, const char *text_end=NULL)
Definition: imgui.cpp:2211
ImGui::DragFloat4
IMGUI_API bool DragFloat4(const char *label, float v[4], float v_speed=1.0f, float v_min=0.0f, float v_max=0.0f, const char *format="%.3f", float power=1.0f)
Definition: imgui_widgets.cpp:1969
ImGuiCol_PlotHistogramHovered
@ ImGuiCol_PlotHistogramHovered
Definition: imgui.h:1030
ImRect
Definition: imgui_internal.h:441
ImGuiButtonFlags_AllowItemOverlap
@ ImGuiButtonFlags_AllowItemOverlap
Definition: imgui_internal.h:284
ImGui::VSliderInt
IMGUI_API bool VSliderInt(const char *label, const ImVec2 &size, int *v, int v_min, int v_max, const char *format="%d")
Definition: imgui_widgets.cpp:2509
ImGui::SetActiveID
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow *window)
Definition: imgui.cpp:2569
ImGuiColorEditFlags_AlphaPreviewHalf
@ ImGuiColorEditFlags_AlphaPreviewHalf
Definition: imgui.h:1102
ImGui::MenuItem
IMGUI_API bool MenuItem(const char *label, const char *shortcut=NULL, bool selected=false, bool enabled=true)
Definition: imgui_widgets.cpp:5709
ImGuiContext::ColorEditOptions
ImGuiColorEditFlags ColorEditOptions
Definition: imgui_internal.h:846
IM_U32_MIN
static const ImU32 IM_U32_MIN
Definition: imgui_widgets.cpp:71
ImGui::SliderInt3
IMGUI_API bool SliderInt3(const char *label, int v[3], int v_min, int v_max, const char *format="%d")
Definition: imgui_widgets.cpp:2434
ImDrawList::PathArcTo
IMGUI_API void PathArcTo(const ImVec2 &centre, float radius, float a_min, float a_max, int num_segments=10)
Definition: imgui_draw.cpp:950
d
d
ImGuiCol_Border
@ ImGuiCol_Border
Definition: imgui.h:994
ImGuiTabItem::LastFrameSelected
int LastFrameSelected
Definition: imgui_internal.h:1211
ImGui::IsKeyPressedMap
bool IsKeyPressedMap(ImGuiKey key, bool repeat=true)
Definition: imgui_internal.h:1347
ImGuiSelectableFlags_Disabled
@ ImGuiSelectableFlags_Disabled
Definition: imgui.h:783
ImGuiCol_ButtonActive
@ ImGuiCol_ButtonActive
Definition: imgui.h:1012
ImGui::TabBarCloseTab
IMGUI_API void TabBarCloseTab(ImGuiTabBar *tab_bar, ImGuiTabItem *tab)
Definition: imgui_widgets.cpp:6109
ImGuiInputTextCallbackData::EventChar
ImWchar EventChar
Definition: imgui.h:1421
ImGuiContext::CurrentTabBar
ImVector< ImGuiTabBar * > CurrentTabBar
Definition: imgui_internal.h:839
ImAtof
static double ImAtof(const char *s)
Definition: imgui_internal.h:211
ImGuiItemStatusFlags_HoveredRect
@ ImGuiItemStatusFlags_HoveredRect
Definition: imgui_internal.h:337
ImGui::TabBarScrollToTab
static void TabBarScrollToTab(ImGuiTabBar *tab_bar, ImGuiTabItem *tab)
Definition: imgui_widgets.cpp:6131
ImGuiContext::NavActivatePressedId
ImGuiID NavActivatePressedId
Definition: imgui_internal.h:778
ImGuiColorEditFlags_RGB
@ ImGuiColorEditFlags_RGB
Definition: imgui.h:1104
ImGui::Checkbox
IMGUI_API bool Checkbox(const char *label, bool *v)
Definition: imgui_widgets.cpp:876
ImGuiWindow::NavRectRel
ImRect NavRectRel[ImGuiNavLayer_COUNT]
Definition: imgui_internal.h:1150
ImGui::AcceptDragDropPayload
const IMGUI_API ImGuiPayload * AcceptDragDropPayload(const char *type, ImGuiDragDropFlags flags=0)
Definition: imgui.cpp:8548
ImGuiWindowFlags_ChildWindow
@ ImGuiWindowFlags_ChildWindow
Definition: imgui.h:712
ImGuiNavForward_ForwardQueued
@ ImGuiNavForward_ForwardQueued
Definition: imgui_internal.h:422
ImRect::GetWidth
float GetWidth() const
Definition: imgui_internal.h:453
ImGui::InputFloat2
IMGUI_API bool InputFloat2(const char *label, float v[2], const char *format="%.3f", ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2735
ImParseFormatTrimDecorations
const char * ImParseFormatTrimDecorations(const char *fmt, char *buf, int buf_size)
Definition: imgui_widgets.cpp:2571
ImGui::TreeNodeBehaviorIsOpen
IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags=0)
Definition: imgui_widgets.cpp:4693
ImGui::TextWrappedV
IMGUI_API void TextWrappedV(const char *fmt, va_list args) IM_FMTLIST(1)
Definition: imgui_widgets.cpp:283
ImDrawCornerFlags_BotLeft
@ ImDrawCornerFlags_BotLeft
Definition: imgui.h:1765
ImGui::IsMousePosValid
IMGUI_API bool IsMousePosValid(const ImVec2 *mouse_pos=NULL)
Definition: imgui.cpp:4084
ImGuiDir_Left
@ ImGuiDir_Left
Definition: imgui.h:892
ImGui::StartMouseMovingWindow
IMGUI_API void StartMouseMovingWindow(ImGuiWindow *window)
Definition: imgui.cpp:3020
ImVec4::x
float x
Definition: imgui.h:178
ImGuiCol_PlotLines
@ ImGuiCol_PlotLines
Definition: imgui.h:1027
ImGui::SetNavIDWithRectRel
IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect &rect_rel)
Definition: imgui.cpp:2559
ImGuiInputReadMode_Pressed
@ ImGuiInputReadMode_Pressed
Definition: imgui_internal.h:384
ImGuiTreeNodeFlags_Leaf
@ ImGuiTreeNodeFlags_Leaf
Definition: imgui.h:762
ImMax
static T ImMax(T lhs, T rhs)
Definition: imgui_internal.h:217
ImGuiCol_TabHovered
@ ImGuiCol_TabHovered
Definition: imgui.h:1023
ImGuiContext
Definition: imgui_internal.h:715
ImU32
unsigned int ImU32
Definition: imgui.h:150
ImGui::InputTextEx
IMGUI_API bool InputTextEx(const char *label, char *buf, int buf_size, const ImVec2 &size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback=NULL, void *user_data=NULL)
Definition: imgui_widgets.cpp:3122
ImFont::CalcTextSizeA
IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char *text_begin, const char *text_end=NULL, const char **remaining=NULL) const
Definition: imgui_draw.cpp:2552
ImRect::Contains
bool Contains(const ImVec2 &p) const
Definition: imgui_internal.h:459
ImGui::FocusableItemUnregister
IMGUI_API void FocusableItemUnregister(ImGuiWindow *window)
Definition: imgui.cpp:2855
ImGuiCol_TabUnfocusedActive
@ ImGuiCol_TabUnfocusedActive
Definition: imgui.h:1026
ImGuiSelectableFlags_AllowDoubleClick
@ ImGuiSelectableFlags_AllowDoubleClick
Definition: imgui.h:782
ImGui::SetNextWindowSize
IMGUI_API void SetNextWindowSize(const ImVec2 &size, ImGuiCond cond=0)
Definition: imgui.cpp:6054
ImGui::RenderRectFilledRangeH
IMGUI_API void RenderRectFilledRangeH(ImDrawList *draw_list, const ImRect &rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding)
Definition: imgui_draw.cpp:2906
ImGuiInputTextFlags_NoUndoRedo
@ ImGuiInputTextFlags_NoUndoRedo
Definition: imgui.h:743
ImGuiDataType_U64
@ ImGuiDataType_U64
Definition: imgui.h:882
ImGuiWindow::ClipRect
ImRect ClipRect
Definition: imgui_internal.h:1129
TabItemComparerByVisibleOffset
static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void *lhs, const void *rhs)
Definition: imgui_widgets.cpp:5809
ImDrawList::AddRectFilled
IMGUI_API void AddRectFilled(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding=0.0f, int rounding_corners_flags=ImDrawCornerFlags_All)
Definition: imgui_draw.cpp:1061
ImGui::SetCursorScreenPos
IMGUI_API void SetCursorScreenPos(const ImVec2 &pos)
Definition: imgui.cpp:6245
ImGui::Value
IMGUI_API void Value(const char *prefix, bool b)
Definition: imgui_widgets.cpp:5372
ImGuiCol_ScrollbarGrabActive
@ ImGuiCol_ScrollbarGrabActive
Definition: imgui.h:1006
ImRect::GetBL
ImVec2 GetBL() const
Definition: imgui_internal.h:457
ImFmod
static float ImFmod(float x, float y)
Definition: imgui_internal.h:205
ImGuiWindow::Pos
ImVec2 Pos
Definition: imgui_internal.h:1085
ImGui::SliderInt4
IMGUI_API bool SliderInt4(const char *label, int v[4], int v_min, int v_max, const char *format="%d")
Definition: imgui_widgets.cpp:2439
ImGuiSeparatorFlags_Horizontal
@ ImGuiSeparatorFlags_Horizontal
Definition: imgui_internal.h:329
ImGui::GetContentRegionAvail
IMGUI_API ImVec2 GetContentRegionAvail()
Definition: imgui.cpp:6109
STB_TEXTEDIT_STRING
#define STB_TEXTEDIT_STRING
Definition: imgui_internal.h:98
ImGuiTreeNodeFlags_NoAutoOpenOnLog
@ ImGuiTreeNodeFlags_NoAutoOpenOnLog
Definition: imgui.h:758
ImGuiTreeNodeFlags_NoTreePushOnOpen
@ ImGuiTreeNodeFlags_NoTreePushOnOpen
Definition: imgui.h:757
ImGuiInputTextCallbackData::Flags
ImGuiInputTextFlags Flags
Definition: imgui.h:1415
ImGui::ColorConvertFloat4ToU32
IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4 &in)
Definition: imgui.cpp:1723
ImGuiComboFlags_None
@ ImGuiComboFlags_None
Definition: imgui.h:789
ImDrawList::PrimVtx
void PrimVtx(const ImVec2 &pos, const ImVec2 &uv, ImU32 col)
Definition: imgui.h:1872
ImGuiTabItemFlags_NoPushId
@ ImGuiTabItemFlags_NoPushId
Definition: imgui.h:823
ImGuiContext::MouseCursor
ImGuiMouseCursor MouseCursor
Definition: imgui_internal.h:818
ImGui::RenderFrameBorder
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding=0.0f)
Definition: imgui.cpp:2325
ImGuiKey_C
@ ImGuiKey_C
Definition: imgui.h:918
ImGui::TabItemLabelAndCloseButton
IMGUI_API bool TabItemLabelAndCloseButton(ImDrawList *draw_list, const ImRect &bb, ImGuiTabItemFlags flags, const char *label, ImGuiID tab_id, ImGuiID close_button_id)
Definition: imgui_widgets.cpp:6482
ImGuiLayoutType
int ImGuiLayoutType
Definition: imgui_internal.h:75
ImGuiInputTextState::TextW
ImVector< ImWchar > TextW
Definition: imgui_internal.h:525
ImGuiPlotArrayGetterData::Values
const float * Values
Definition: imgui_widgets.cpp:5330
ImFabs
static float ImFabs(float x)
Definition: imgui_internal.h:201
ImGuiStyleVar_WindowRounding
@ ImGuiStyleVar_WindowRounding
Definition: imgui.h:1057
ImGuiWindow::DC
ImGuiWindowTempData DC
Definition: imgui_internal.h:1127
ImGuiColorEditFlags__PickerMask
@ ImGuiColorEditFlags__PickerMask
Definition: imgui.h:1115
ImDrawList::VtxBuffer
ImVector< ImDrawVert > VtxBuffer
Definition: imgui.h:1792
ImGuiStb::STB_TEXTEDIT_LAYOUTROW
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow *r, STB_TEXTEDIT_STRING *obj, int line_start_idx)
Definition: imgui_widgets.cpp:2899
STB_TEXTEDIT_K_TEXTSTART
#define STB_TEXTEDIT_K_TEXTSTART
Definition: imgui_widgets.cpp:2977
ImGuiColorEditFlags_HEX
@ ImGuiColorEditFlags_HEX
Definition: imgui.h:1106
IM_F32_TO_INT8_UNBOUND
#define IM_F32_TO_INT8_UNBOUND(_VAL)
Definition: imgui_internal.h:125
ImGui::PopStyleVar
IMGUI_API void PopStyleVar(int count=1)
Definition: imgui.cpp:5725
ImGui::ColorEditOptionsPopup
IMGUI_API void ColorEditOptionsPopup(const float *col, ImGuiColorEditFlags flags)
Definition: imgui_widgets.cpp:4506
ImGuiContext::BeginPopupStack
ImVector< ImGuiPopupRef > BeginPopupStack
Definition: imgui_internal.h:768
ImGuiContext::ActiveIdAllowNavDirFlags
int ActiveIdAllowNavDirFlags
Definition: imgui_internal.h:755
ImGuiAxis
ImGuiAxis
Definition: imgui_internal.h:357
ImGuiPlotType_Lines
@ ImGuiPlotType_Lines
Definition: imgui_internal.h:366
ImGuiWindow
Definition: imgui_internal.h:1080
ImFormatStringV
int ImFormatStringV(char *buf, size_t buf_size, const char *fmt, va_list args)
Definition: imgui.cpp:1405
ImGui::CollapsingHeader
IMGUI_API bool CollapsingHeader(const char *label, ImGuiTreeNodeFlags flags=0)
Definition: imgui_widgets.cpp:4954
ImRect::GetTL
ImVec2 GetTL() const
Definition: imgui_internal.h:455
ImGui::InputInt
IMGUI_API bool InputInt(const char *label, int *v, int step=1, int step_fast=100, ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2785
ImGui::InputFloat3
IMGUI_API bool InputFloat3(const char *label, float v[3], const char *format="%.3f", ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2740
ImGui::EndMainMenuBar
IMGUI_API void EndMainMenuBar()
Definition: imgui_widgets.cpp:5477
ImGuiItemFlags_NoNav
@ ImGuiItemFlags_NoNav
Definition: imgui_internal.h:994
ImGui::TreeNodeBehavior
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char *label, const char *label_end=NULL)
Definition: imgui_widgets.cpp:4740
ImGuiKey_Escape
@ ImGuiKey_Escape
Definition: imgui.h:916
ImGuiStyle::GrabMinSize
float GrabMinSize
Definition: imgui.h:1246
ImAtoi
static const char * ImAtoi(const char *src, TYPE *output)
Definition: imgui_widgets.cpp:1667
ImGui::CalcTextSize
IMGUI_API ImVec2 CalcTextSize(const char *text, const char *text_end=NULL, bool hide_text_after_double_hash=false, float wrap_width=-1.0f)
Definition: imgui.cpp:3827
ImGuiTabBar::WantLayout
bool WantLayout
Definition: imgui_internal.h:1238
ImGui::TextWrapped
IMGUI_API void TextWrapped(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui_widgets.cpp:275
ImGuiWindowTempData::MenuBarOffset
ImVec2 MenuBarOffset
Definition: imgui_internal.h:1026
ImRect::GetCenter
ImVec2 GetCenter() const
Definition: imgui_internal.h:451
ImGui::ArrowButton
IMGUI_API bool ArrowButton(const char *str_id, ImGuiDir dir)
Definition: imgui_widgets.cpp:644
ImGui::TextV
IMGUI_API void TextV(const char *fmt, va_list args) IM_FMTLIST(1)
Definition: imgui_widgets.cpp:234
IM_COL32_BLACK
#define IM_COL32_BLACK
Definition: imgui.h:1684
ImGui::ColorButton
IMGUI_API bool ColorButton(const char *desc_id, const ImVec4 &col, ImGuiColorEditFlags flags=0, ImVec2 size=ImVec2(0, 0))
Definition: imgui_widgets.cpp:4391
ImGuiStyle::GrabRounding
float GrabRounding
Definition: imgui.h:1247
ImDrawList::AddCircleFilled
IMGUI_API void AddCircleFilled(const ImVec2 &centre, float radius, ImU32 col, int num_segments=12)
Definition: imgui_draw.cpp:1148
ImGuiIO::InputQueueCharacters
ImVector< ImWchar > InputQueueCharacters
Definition: imgui.h:1395
ImGui::MarkIniSettingsDirty
IMGUI_API void MarkIniSettingsDirty()
Definition: imgui.cpp:8784
ImGui::InputText
IMGUI_API bool InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags=0, ImGuiInputTextCallback callback=NULL, void *user_data=NULL)
Definition: imgui_widgets.cpp:2821
ImGuiContext::NavMoveRequestForward
ImGuiNavForward NavMoveRequestForward
Definition: imgui_internal.h:806
ImGui::EndTooltip
IMGUI_API void EndTooltip()
Definition: imgui.cpp:6559
ImAlphaBlendColor
static ImU32 ImAlphaBlendColor(ImU32 col_a, ImU32 col_b)
Definition: imgui_widgets.cpp:4026
ImGuiCond_Always
@ ImGuiCond_Always
Definition: imgui.h:1145
InputTextCalcTextLenAndLineCount
static int InputTextCalcTextLenAndLineCount(const char *text_begin, const char **out_text_end)
Definition: imgui_widgets.cpp:2832
ImFont::GetCharAdvance
float GetCharAdvance(ImWchar c) const
Definition: imgui.h:2100
ImGui::DragInt
IMGUI_API bool DragInt(const char *label, int *v, float v_speed=1.0f, int v_min=0, int v_max=0, const char *format="%d")
Definition: imgui_widgets.cpp:1999
ImGuiIO::MousePos
ImVec2 MousePos
Definition: imgui.h:1341
ImGui::DragScalar
IMGUI_API bool DragScalar(const char *label, ImGuiDataType data_type, void *v, float v_speed, const void *v_min=NULL, const void *v_max=NULL, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:1848
ImGuiWindow::MenuColumns
ImGuiMenuColumns MenuColumns
Definition: imgui_internal.h:1135
ImGui::PopClipRect
IMGUI_API void PopClipRect()
Definition: imgui.cpp:3682
ImGuiInputTextCallbackData::InsertChars
IMGUI_API void InsertChars(int pos, const char *text, const char *text_end=NULL)
Definition: imgui_widgets.cpp:3025
IM_COL32_A_SHIFT
#define IM_COL32_A_SHIFT
Definition: imgui.h:1679
ImGui::RenderTextClippedEx
IMGUI_API void RenderTextClippedEx(ImDrawList *draw_list, const ImVec2 &pos_min, const ImVec2 &pos_max, const char *text, const char *text_end, const ImVec2 *text_size_if_known, const ImVec2 &align=ImVec2(0, 0), const ImRect *clip_rect=NULL)
Definition: imgui.cpp:2268
ImGuiTabBarSortItem
Definition: imgui_internal.h:705
ImGuiInputTextFlags_CallbackCharFilter
@ ImGuiInputTextFlags_CallbackCharFilter
Definition: imgui.h:736
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem
@ ImGuiHoveredFlags_AllowWhenBlockedByActiveItem
Definition: imgui.h:847
ImGui::AlignTextToFramePadding
IMGUI_API void AlignTextToFramePadding()
Definition: imgui_widgets.cpp:1117
ImGui::RenderFrame
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border=true, float rounding=0.0f)
Definition: imgui.cpp:2312
ImGuiDir_Down
@ ImGuiDir_Down
Definition: imgui.h:895
ImGuiTreeNodeFlags_OpenOnDoubleClick
@ ImGuiTreeNodeFlags_OpenOnDoubleClick
Definition: imgui.h:760
ImGui::Indent
IMGUI_API void Indent(float indent_w=0.0f)
Definition: imgui.cpp:6499
ImGui::ColorEdit3
IMGUI_API bool ColorEdit3(const char *label, float col[3], ImGuiColorEditFlags flags=0)
Definition: imgui_widgets.cpp:3806
ImGuiTabBarFlags_FittingPolicyMask_
@ ImGuiTabBarFlags_FittingPolicyMask_
Definition: imgui.h:812
ImDrawList::AddConvexPolyFilled
IMGUI_API void AddConvexPolyFilled(const ImVec2 *points, const int num_points, ImU32 col)
Definition: imgui_draw.cpp:854
ImGui::ColorTooltip
IMGUI_API void ColorTooltip(const char *text, const float *col, ImGuiColorEditFlags flags)
Definition: imgui_widgets.cpp:4482
ImGui::TextUnformatted
IMGUI_API void TextUnformatted(const char *text, const char *text_end=NULL)
Definition: imgui_widgets.cpp:119
ImGuiColorEditFlags_NoAlpha
@ ImGuiColorEditFlags_NoAlpha
Definition: imgui.h:1089
ImSin
static float ImSin(float x)
Definition: imgui_internal.h:208
ImGuiStb::STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui_widgets.cpp:2919
ImGuiDataType_S64
@ ImGuiDataType_S64
Definition: imgui.h:881
ImGuiNavHighlightFlags_TypeThin
@ ImGuiNavHighlightFlags_TypeThin
Definition: imgui_internal.h:395
ImAtan2
static float ImAtan2(float y, float x)
Definition: imgui_internal.h:210
ImGui::TabBarScrollingButtons
static ImGuiTabItem * TabBarScrollingButtons(ImGuiTabBar *tab_bar)
Definition: imgui_widgets.cpp:6152
STB_TEXTEDIT_K_UP
#define STB_TEXTEDIT_K_UP
Definition: imgui_widgets.cpp:2973
ImGui::Bullet
IMGUI_API void Bullet()
Definition: imgui_widgets.cpp:1048
ImGuiTabBar::ReorderRequestTabId
ImGuiID ReorderRequestTabId
Definition: imgui_internal.h:1236
ImGuiMenuColumns::Count
int Count
Definition: imgui_internal.h:510
ImGuiSelectableFlags
int ImGuiSelectableFlags
Definition: imgui.h:140
ImGuiWindow::MoveId
ImGuiID MoveId
Definition: imgui_internal.h:1095
ImGuiWindowTempData::CurrentLineTextBaseOffset
float CurrentLineTextBaseOffset
Definition: imgui_internal.h:1009
ImGuiInputTextCallbackData::DeleteChars
IMGUI_API void DeleteChars(int pos, int bytes_count)
Definition: imgui_widgets.cpp:3007
ImGuiColorEditFlags_NoLabel
@ ImGuiColorEditFlags_NoLabel
Definition: imgui.h:1095
ImGuiStyle::ScrollbarRounding
float ScrollbarRounding
Definition: imgui.h:1245
ImGuiIO::MouseDoubleClicked
bool MouseDoubleClicked[5]
Definition: imgui.h:1384
ImGuiTabBarFlags_Reorderable
@ ImGuiTabBarFlags_Reorderable
Definition: imgui.h:804
ImGuiTreeNodeFlags_Selected
@ ImGuiTreeNodeFlags_Selected
Definition: imgui.h:754
ImGuiInputTextState::ClearSelection
void ClearSelection()
Definition: imgui_internal.h:545
ImGuiStb::STB_TEXTEDIT_KEYTOTEXT
static int STB_TEXTEDIT_KEYTOTEXT(int key)
Definition: imgui_widgets.cpp:2897
ImGui::PopItemWidth
IMGUI_API void PopItemWidth()
Definition: imgui.cpp:5517
ImGuiWindow::WindowBorderSize
float WindowBorderSize
Definition: imgui_internal.h:1093
ImGuiWindow::ScrollbarX
bool ScrollbarX
Definition: imgui_internal.h:1101
ImGuiNavHighlightFlags_NoRounding
@ ImGuiNavHighlightFlags_NoRounding
Definition: imgui_internal.h:397
ImGuiWindow::OuterRectClipped
ImRect OuterRectClipped
Definition: imgui_internal.h:1130
ImGui::SetWindowScrollY
IMGUI_API void SetWindowScrollY(ImGuiWindow *window, float new_scroll_y)
Definition: imgui.cpp:5908
ImGuiInputTextState::CurLenA
int CurLenA
Definition: imgui_internal.h:528
ImGuiStyle::FrameBorderSize
float FrameBorderSize
Definition: imgui.h:1238
IM_COL32_WHITE
#define IM_COL32_WHITE
Definition: imgui.h:1683
ImGuiDataTypeInfo::PrintFmt
const char * PrintFmt
Definition: imgui_widgets.cpp:1481
ImGuiWindowFlags_NoMove
@ ImGuiWindowFlags_NoMove
Definition: imgui.h:688
ImGuiInputTextFlags_AllowTabInput
@ ImGuiInputTextFlags_AllowTabInput
Definition: imgui.h:737
ImGui::SetDragDropPayload
IMGUI_API bool SetDragDropPayload(const char *type, const void *data, size_t size, ImGuiCond cond=0)
Definition: imgui.cpp:8447
ImGuiTabBarFlags_NoTooltip
@ ImGuiTabBarFlags_NoTooltip
Definition: imgui.h:809
values
std::vector< double > values
ImGuiColorEditFlags_PickerHueWheel
@ ImGuiColorEditFlags_PickerHueWheel
Definition: imgui.h:1110
ImGuiWindowTempData::MenuBarAppending
bool MenuBarAppending
Definition: imgui_internal.h:1025
ImGuiInputTextCallbackData::Buf
char * Buf
Definition: imgui.h:1423
ImDrawCornerFlags_Left
@ ImDrawCornerFlags_Left
Definition: imgui.h:1769
ImGui::GetTextLineHeight
IMGUI_API float GetTextLineHeight()
Definition: imgui.cpp:6139
ImGui::NavMoveRequestButNoResultYet
IMGUI_API bool NavMoveRequestButNoResultYet()
Definition: imgui.cpp:7210
ImGui::EndTabItem
IMGUI_API void EndTabItem()
Definition: imgui_widgets.cpp:6238
ImGuiMenuColumns::Spacing
float Spacing
Definition: imgui_internal.h:511
ImGuiCol_Tab
@ ImGuiCol_Tab
Definition: imgui.h:1022
ImGui::BeginTooltipEx
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip=true)
Definition: imgui.cpp:6541
ImDrawCornerFlags_BotRight
@ ImDrawCornerFlags_BotRight
Definition: imgui.h:1766
ImLerp
static T ImLerp(T a, T b, float t)
Definition: imgui_internal.h:219
ImGuiIO::DisplaySize
ImVec2 DisplaySize
Definition: imgui.h:1277
ImGuiDragFlags_None
@ ImGuiDragFlags_None
Definition: imgui_internal.h:302
ImGuiInputTextCallbackData
Definition: imgui.h:1412
ImGuiStb::STB_TEXTEDIT_DELETECHARS
static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING *obj, int pos, int n)
Definition: imgui_widgets.cpp:2924
ImGuiStorage::SetInt
IMGUI_API void SetInt(ImGuiID key, int val)
Definition: imgui.cpp:1921
ImRect::GetHeight
float GetHeight() const
Definition: imgui_internal.h:454
ImGui::IsNavInputDown
bool IsNavInputDown(ImGuiNavInput n)
Definition: imgui_internal.h:1348
ImGui::PushMultiItemsWidths
IMGUI_API void PushMultiItemsWidths(int components, float width_full=0.0f)
Definition: imgui.cpp:5503
ImGui::InputDouble
IMGUI_API bool InputDouble(const char *label, double *v, double step=0.0f, double step_fast=0.0f, const char *format="%.6f", ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2807
ImGui::PopTextWrapPos
IMGUI_API void PopTextWrapPos()
Definition: imgui.cpp:5616
ImGuiStyle::Colors
ImVec4 Colors[ImGuiCol_COUNT]
Definition: imgui.h:1257
ImDrawList::PathLineTo
void PathLineTo(const ImVec2 &pos)
Definition: imgui.h:1841
ImGuiInputTextCallbackData::BufSize
int BufSize
Definition: imgui.h:1425
ImGui::TreeAdvanceToLabelPos
IMGUI_API void TreeAdvanceToLabelPos()
Definition: imgui_widgets.cpp:4930
ImGuiWindow::Size
ImVec2 Size
Definition: imgui_internal.h:1086
ImVector::resize
void resize(int new_size)
Definition: imgui.h:1201
GetMinimumStepAtDecimalPrecision
static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
Definition: imgui_widgets.cpp:1658
ImQsort
#define ImQsort
Definition: imgui_internal.h:151
ImGuiWindowFlags_NoNavFocus
@ ImGuiWindowFlags_NoNavFocus
Definition: imgui.h:704
ImGuiSelectableFlags_NoHoldingActiveID
@ ImGuiSelectableFlags_NoHoldingActiveID
Definition: imgui_internal.h:320
ImDrawCornerFlags_Right
@ ImDrawCornerFlags_Right
Definition: imgui.h:1770
ImFont::Ascent
float Ascent
Definition: imgui.h:2088
ImGui::Begin
IMGUI_API bool Begin(const char *name, bool *p_open=NULL, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:4736
ImGuiContext::NavMoveDir
ImGuiDir NavMoveDir
Definition: imgui_internal.h:807
ImGuiDragFlags
int ImGuiDragFlags
Definition: imgui_internal.h:87
STB_TEXTEDIT_K_DOWN
#define STB_TEXTEDIT_K_DOWN
Definition: imgui_widgets.cpp:2974
ImGuiMenuColumns::NextWidths
float NextWidths[4]
Definition: imgui_internal.h:513
ImGui::VerticalSeparator
IMGUI_API void VerticalSeparator()
Definition: imgui_widgets.cpp:1175
ImGuiWindow::ScrollbarY
bool ScrollbarY
Definition: imgui_internal.h:1101
ImGui::SliderAngle
IMGUI_API bool SliderAngle(const char *label, float *v_rad, float v_degrees_min=-360.0f, float v_degrees_max=+360.0f, const char *format="%.0f deg")
Definition: imgui_widgets.cpp:2414
GetOverlayDrawList
static ImDrawList * GetOverlayDrawList(ImGuiWindow *)
Definition: imgui.cpp:3004
ImVec4::w
float w
Definition: imgui.h:178
ImGuiTabBarFlags_NoTabListScrollingButtons
@ ImGuiTabBarFlags_NoTabListScrollingButtons
Definition: imgui.h:808
ImGuiWindow::MenuBarHeight
float MenuBarHeight() const
Definition: imgui_internal.h:1176
ImGuiContext::HoveredId
ImGuiID HoveredId
Definition: imgui_internal.h:741
ImGuiStyle::WindowPadding
ImVec2 WindowPadding
Definition: imgui.h:1227
ImGuiTreeNodeFlags_DefaultOpen
@ ImGuiTreeNodeFlags_DefaultOpen
Definition: imgui.h:759
ImGuiDragDropFlags_SourceNoHoldToOpenOthers
@ ImGuiDragDropFlags_SourceNoHoldToOpenOthers
Definition: imgui.h:861
ImGuiMouseCursor_TextInput
@ ImGuiMouseCursor_TextInput
Definition: imgui.h:1125
ImGuiSliderFlags_Vertical
@ ImGuiSliderFlags_Vertical
Definition: imgui_internal.h:297
ImGuiContext::TempBuffer
char TempBuffer[1024 *3+1]
Definition: imgui_internal.h:879
ImGui::ButtonBehavior
IMGUI_API bool ButtonBehavior(const ImRect &bb, ImGuiID id, bool *out_hovered, bool *out_held, ImGuiButtonFlags flags=0)
Definition: imgui_widgets.cpp:380
ImGui::PushStyleVar
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val)
Definition: imgui.cpp:5697
ImGuiTabBar::OffsetNextTab
float OffsetNextTab
Definition: imgui_internal.h:1232
ImVector::empty
bool empty() const
Definition: imgui.h:1183
ImGuiStorage
Definition: imgui.h:1597
ImGuiCol_SliderGrabActive
@ ImGuiCol_SliderGrabActive
Definition: imgui.h:1009
ImGui::IsNavInputPressed
bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode)
Definition: imgui_internal.h:1349
ImGuiColorEditFlags_NoOptions
@ ImGuiColorEditFlags_NoOptions
Definition: imgui.h:1091
ImGui::RenderPixelEllipsis
IMGUI_API void RenderPixelEllipsis(ImDrawList *draw_list, ImVec2 pos, int count, ImU32 col)
Definition: imgui_draw.cpp:2968
ImGuiItemFlags_ButtonRepeat
@ ImGuiItemFlags_ButtonRepeat
Definition: imgui_internal.h:992
ImGuiStyle::TabBorderSize
float TabBorderSize
Definition: imgui.h:1249
ImGui::ColorPicker3
IMGUI_API bool ColorPicker3(const char *label, float col[3], ImGuiColorEditFlags flags=0)
Definition: imgui_widgets.cpp:4017
ImGuiWindow::IDStack
ImVector< ImGuiID > IDStack
Definition: imgui_internal.h:1128
ImGuiInputTextState::SelectedAllMouseLock
bool SelectedAllMouseLock
Definition: imgui_internal.h:534
ImGui::TreePush
IMGUI_API void TreePush(const char *str_id)
Definition: imgui_widgets.cpp:4887
ImGuiTreeNodeFlags_Bullet
@ ImGuiTreeNodeFlags_Bullet
Definition: imgui.h:763
ImGui::BeginMenuBar
IMGUI_API bool BeginMenuBar()
Definition: imgui_widgets.cpp:5489
ImGui::ItemSize
IMGUI_API void ItemSize(const ImVec2 &size, float text_offset_y=0.0f)
Definition: imgui.cpp:2679
ImGui::TabItemBackground
IMGUI_API void TabItemBackground(ImDrawList *draw_list, const ImRect &bb, ImGuiTabItemFlags flags, ImU32 col)
Definition: imgui_widgets.cpp:6461
ImGuiWindow::Rect
ImRect Rect() const
Definition: imgui_internal.h:1172
ImGuiTabItemFlags_UnsavedDocument
@ ImGuiTabItemFlags_UnsavedDocument
Definition: imgui.h:820
ImGuiItemStatusFlags_HasDisplayRect
@ ImGuiItemStatusFlags_HasDisplayRect
Definition: imgui_internal.h:338
ImGui::VSliderScalar
IMGUI_API bool VSliderScalar(const char *label, const ImVec2 &size, ImGuiDataType data_type, void *v, const void *v_min, const void *v_max, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:2444
ImGui::SameLine
IMGUI_API void SameLine(float local_pos_x=0.0f, float spacing_w=-1.0f)
Definition: imgui.cpp:6476
ImGui::MemFree
IMGUI_API void MemFree(void *ptr)
Definition: imgui.cpp:2895
ImGuiContext::ScalarAsInputTextId
ImGuiID ScalarAsInputTextId
Definition: imgui_internal.h:845
ImGui::DragFloat2
IMGUI_API bool DragFloat2(const char *label, float v[2], float v_speed=1.0f, float v_min=0.0f, float v_max=0.0f, const char *format="%.3f", float power=1.0f)
Definition: imgui_widgets.cpp:1959
ImGui::DragFloat3
IMGUI_API bool DragFloat3(const char *label, float v[3], float v_speed=1.0f, float v_min=0.0f, float v_max=0.0f, const char *format="%.3f", float power=1.0f)
Definition: imgui_widgets.cpp:1964
ImGuiCol_FrameBg
@ ImGuiCol_FrameBg
Definition: imgui.h:996
ImGui::TabBarQueueChangeTabOrder
IMGUI_API void TabBarQueueChangeTabOrder(ImGuiTabBar *tab_bar, const ImGuiTabItem *tab, int dir)
Definition: imgui_widgets.cpp:6144
ImGuiContext::WantTextInputNextFrame
int WantTextInputNextFrame
Definition: imgui_internal.h:878
ImGuiTabBarFlags_FittingPolicyDefault_
@ ImGuiTabBarFlags_FittingPolicyDefault_
Definition: imgui.h:813
ImGuiIO
Definition: imgui.h:1269
ImFont
Definition: imgui.h:2071
PatchFormatStringFloatToInt
static const char * PatchFormatStringFloatToInt(const char *fmt)
Definition: imgui_widgets.cpp:1504
ImGuiContext::NavLayer
ImGuiNavLayer NavLayer
Definition: imgui_internal.h:792
ImGuiButtonFlags_FlattenChildren
@ ImGuiButtonFlags_FlattenChildren
Definition: imgui_internal.h:283
STB_TEXTEDIT_K_SHIFT
#define STB_TEXTEDIT_K_SHIFT
Definition: imgui_widgets.cpp:2985
ImGuiMenuColumns::Update
void Update(int count, float spacing, bool clear)
Definition: imgui_widgets.cpp:5423
ImGuiInputTextFlags
int ImGuiInputTextFlags
Definition: imgui.h:139
ImGuiWindowTempData::Indent
ImVec1 Indent
Definition: imgui_internal.h:1042
ImGuiStyle::FramePadding
ImVec2 FramePadding
Definition: imgui.h:1236
ImGui::ListBox
IMGUI_API bool ListBox(const char *label, int *current_item, const char *const items[], int items_count, int height_in_items=-1)
Definition: imgui_widgets.cpp:5170
ImCharIsBlankA
static bool ImCharIsBlankA(char c)
Definition: imgui_internal.h:147
ImGui::RenderBullet
IMGUI_API void RenderBullet(ImVec2 pos)
Definition: imgui.cpp:2372
ImGui::FocusWindow
IMGUI_API void FocusWindow(ImGuiWindow *window)
Definition: imgui.cpp:5444
ImGui::SliderBehavior
IMGUI_API bool SliderBehavior(const ImRect &bb, ImGuiID id, ImGuiDataType data_type, void *v, const void *v_min, const void *v_max, const char *format, float power, ImGuiSliderFlags flags, ImRect *out_grab_bb)
Definition: imgui_widgets.cpp:2258
Items_SingleStringGetter
static bool Items_SingleStringGetter(void *data, int idx, const char **out_text)
Definition: imgui_widgets.cpp:1385
ImGuiTabBar::CurrFrameVisible
int CurrFrameVisible
Definition: imgui_internal.h:1227
ImGuiStyle::TabRounding
float TabRounding
Definition: imgui.h:1248
ImGuiKey_Backspace
@ ImGuiKey_Backspace
Definition: imgui.h:913
ImGuiComboFlags_NoArrowButton
@ ImGuiComboFlags_NoArrowButton
Definition: imgui.h:795
ImVec4
Definition: imgui.h:176
ImGuiStyleVar_WindowPadding
@ ImGuiStyleVar_WindowPadding
Definition: imgui.h:1056
ImGuiContext::OpenPopupStack
ImVector< ImGuiPopupRef > OpenPopupStack
Definition: imgui_internal.h:767
ImGui::RoundScalarWithFormatT
IMGUI_API T RoundScalarWithFormatT(const char *format, ImGuiDataType data_type, T v)
ImGuiWindow::GetIDNoKeepAlive
ImGuiID GetIDNoKeepAlive(const char *str, const char *str_end=NULL)
Definition: imgui.cpp:2520
ImGui::SetMouseCursor
IMGUI_API void SetMouseCursor(ImGuiMouseCursor type)
Definition: imgui.cpp:4120
ImGui::RenderTextWrapped
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char *text, const char *text_end, float wrap_width)
Definition: imgui.cpp:2250
ImStrTrimBlanks
void ImStrTrimBlanks(char *buf)
Definition: imgui.cpp:1357
IM_ASSERT
#define IM_ASSERT(_EXPR)
Definition: imgui.h:64
ImGuiContext::ColorPickerRef
ImVec4 ColorPickerRef
Definition: imgui_internal.h:847
ImGuiKey_UpArrow
@ ImGuiKey_UpArrow
Definition: imgui.h:905
ImGui::SetClipboardText
IMGUI_API void SetClipboardText(const char *text)
Definition: imgui.cpp:2908
ImGui::GetFrameHeight
IMGUI_API float GetFrameHeight()
Definition: imgui.cpp:6151
ImGuiButtonFlags_NoHoldingActiveID
@ ImGuiButtonFlags_NoHoldingActiveID
Definition: imgui_internal.h:289
ImGui::CloseCurrentPopup
IMGUI_API void CloseCurrentPopup()
Definition: imgui.cpp:6736
ImGui::ImageButton
IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &uv0=ImVec2(0, 0), const ImVec2 &uv1=ImVec2(1, 1), int frame_padding=-1, const ImVec4 &bg_col=ImVec4(0, 0, 0, 0), const ImVec4 &tint_col=ImVec4(1, 1, 1, 1))
Definition: imgui_widgets.cpp:840
IM_F32_TO_INT8_SAT
#define IM_F32_TO_INT8_SAT(_VAL)
Definition: imgui_internal.h:126
ImFontGlyph::AdvanceX
float AdvanceX
Definition: imgui.h:1930
IM_PI
#define IM_PI
Definition: imgui_internal.h:117
args
ImGuiContext::LogEnabled
bool LogEnabled
Definition: imgui_internal.h:866
ImGuiContext::ActiveIdClickOffset
ImVec2 ActiveIdClickOffset
Definition: imgui_internal.h:756
ImGuiPlotType
ImGuiPlotType
Definition: imgui_internal.h:364
ImGuiWindowFlags_NoTitleBar
@ ImGuiWindowFlags_NoTitleBar
Definition: imgui.h:686
ImGuiTabItem::LastFrameVisible
int LastFrameVisible
Definition: imgui_internal.h:1210
STB_TEXTEDIT_K_BACKSPACE
#define STB_TEXTEDIT_K_BACKSPACE
Definition: imgui_widgets.cpp:2980
ImGuiCol_BorderShadow
@ ImGuiCol_BorderShadow
Definition: imgui.h:995
ImGui::BeginTabBarEx
IMGUI_API bool BeginTabBarEx(ImGuiTabBar *tab_bar, const ImRect &bb, ImGuiTabBarFlags flags)
Definition: imgui_widgets.cpp:5839
ImGuiInputTextState::UserFlags
ImGuiInputTextFlags UserFlags
Definition: imgui_internal.h:537
ImGui::SliderFloat4
IMGUI_API bool SliderFloat4(const char *label, float v[4], float v_min, float v_max, const char *format="%.3f", float power=1.0f)
Definition: imgui_widgets.cpp:2409
ImGui::GetStyle
IMGUI_API ImGuiStyle & GetStyle()
Definition: imgui.cpp:2981
ImGuiInputTextFlags_CtrlEnterForNewLine
@ ImGuiInputTextFlags_CtrlEnterForNewLine
Definition: imgui.h:738
ImGui::BeginMainMenuBar
IMGUI_API bool BeginMainMenuBar()
Definition: imgui_widgets.cpp:5457
ImGuiComboFlags
int ImGuiComboFlags
Definition: imgui.h:135
ImGuiInputTextCallbackData::ImGuiInputTextCallbackData
IMGUI_API ImGuiInputTextCallbackData()
Definition: imgui_widgets.cpp:2999
ImGui::SliderCalcRatioFromValueT
IMGUI_API float SliderCalcRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, float power, float linear_zero_pos)
ImGui
Definition: imgui.cpp:1009
ImGuiKey_Insert
@ ImGuiKey_Insert
Definition: imgui.h:911
ImGuiWindowTempData::LastItemId
ImGuiID LastItemId
Definition: imgui_internal.h:1015
ImGuiTabItemFlags_SetSelected
@ ImGuiTabItemFlags_SetSelected
Definition: imgui.h:821
ImGuiInputTextFlags_CharsUppercase
@ ImGuiInputTextFlags_CharsUppercase
Definition: imgui.h:729
ImGuiInputTextFlags_AlwaysInsertMode
@ ImGuiInputTextFlags_AlwaysInsertMode
Definition: imgui.h:740
ImGuiTabItem::Flags
ImGuiTabItemFlags Flags
Definition: imgui_internal.h:1209
ImGuiMenuColumns::ImGuiMenuColumns
ImGuiMenuColumns()
Definition: imgui_widgets.cpp:5415
ImGui::PushClipRect
IMGUI_API void PushClipRect(const ImVec2 &clip_rect_min, const ImVec2 &clip_rect_max, bool intersect_with_current_clip_rect)
Definition: imgui.cpp:3675
ImGui::Scrollbar
IMGUI_API void Scrollbar(ImGuiLayoutType direction)
Definition: imgui_widgets.cpp:707
ImGuiLayoutType_Horizontal
@ ImGuiLayoutType_Horizontal
Definition: imgui_internal.h:354
ImGuiButtonFlags_None
@ ImGuiButtonFlags_None
Definition: imgui_internal.h:277
ImGuiWindowFlags_NoResize
@ ImGuiWindowFlags_NoResize
Definition: imgui.h:687
ImRect::ClipWith
void ClipWith(const ImRect &r)
Definition: imgui_internal.h:469
ImGui::SetTabItemClosed
IMGUI_API void SetTabItemClosed(const char *tab_or_docked_window_label)
Definition: imgui_widgets.cpp:6436
ImGuiContext::CurrentWindow
ImGuiWindow * CurrentWindow
Definition: imgui_internal.h:738
IM_S64_MIN
static const ImS64 IM_S64_MIN
Definition: imgui_widgets.cpp:77
ImGuiTabBarSortItem::Index
int Index
Definition: imgui_internal.h:707
DataTypeApplyOp
static void DataTypeApplyOp(ImGuiDataType data_type, int op, void *output, void *arg_1, const void *arg_2)
Definition: imgui_widgets.cpp:1540
ImGuiWindowTempData::ParentLayoutType
ImGuiLayoutType ParentLayoutType
Definition: imgui_internal.h:1030
ImGuiWindow::GetID
ImGuiID GetID(const char *str, const char *str_end=NULL)
Definition: imgui.cpp:2504
ImGuiColorEditFlags_Float
@ ImGuiColorEditFlags_Float
Definition: imgui.h:1108
ImGui::GetContentRegionMax
IMGUI_API ImVec2 GetContentRegionMax()
Definition: imgui.cpp:6100
STB_TEXTEDIT_K_WORDLEFT
#define STB_TEXTEDIT_K_WORDLEFT
Definition: imgui_widgets.cpp:2983
ImGuiColorEditFlags_NoSmallPreview
@ ImGuiColorEditFlags_NoSmallPreview
Definition: imgui.h:1092
ImGuiTabBarFlags_DockNodeIsDockSpace
@ ImGuiTabBarFlags_DockNodeIsDockSpace
Definition: imgui_internal.h:1200
ImVector::pop_back
void pop_back()
Definition: imgui.h:1207
StbTexteditRow
Definition: imstb_textedit.h:360
ImGuiDir_Right
@ ImGuiDir_Right
Definition: imgui.h:893
ImGui::TreeNodeExV
IMGUI_API bool TreeNodeExV(const char *str_id, ImGuiTreeNodeFlags flags, const char *fmt, va_list args) IM_FMTLIST(3)
Definition: imgui_widgets.cpp:4671
ImGuiTabBar::BarRect
ImRect BarRect
Definition: imgui_internal.h:1229
ImGui::TabBarScrollClamp
static float TabBarScrollClamp(ImGuiTabBar *tab_bar, float scrolling)
Definition: imgui_widgets.cpp:6125
ImGui::OpenPopup
IMGUI_API void OpenPopup(const char *str_id)
Definition: imgui.cpp:6610
ImGuiCol_ScrollbarBg
@ ImGuiCol_ScrollbarBg
Definition: imgui.h:1003
ImGuiIO::DeltaTime
float DeltaTime
Definition: imgui.h:1278
ImGuiCol_FrameBgHovered
@ ImGuiCol_FrameBgHovered
Definition: imgui.h:997
STB_TEXTEDIT_K_RIGHT
#define STB_TEXTEDIT_K_RIGHT
Definition: imgui_widgets.cpp:2972
ImGui::OpenPopupEx
IMGUI_API void OpenPopupEx(ImGuiID id)
Definition: imgui.cpp:6620
ImGuiContext::DragCurrentAccumDirty
bool DragCurrentAccumDirty
Definition: imgui_internal.h:848
ImGui::EndDragDropTarget
IMGUI_API void EndDragDropTarget()
Definition: imgui.cpp:8598
ImGuiStyle::ScrollbarSize
float ScrollbarSize
Definition: imgui.h:1244
ImGui::SliderInt
IMGUI_API bool SliderInt(const char *label, int *v, int v_min, int v_max, const char *format="%d")
Definition: imgui_widgets.cpp:2424
ImGuiDragFlags_Vertical
@ ImGuiDragFlags_Vertical
Definition: imgui_internal.h:303
ImLengthSqr
static float ImLengthSqr(const ImVec2 &lhs)
Definition: imgui_internal.h:229
ImGuiTabBar::VisibleTabId
ImGuiID VisibleTabId
Definition: imgui_internal.h:1226
STB_TEXTEDIT_K_TEXTEND
#define STB_TEXTEDIT_K_TEXTEND
Definition: imgui_widgets.cpp:2978
ImGui::TabItemEx
IMGUI_API bool TabItemEx(ImGuiTabBar *tab_bar, const char *label, bool *p_open, ImGuiTabItemFlags flags)
Definition: imgui_widgets.cpp:6252
ImGuiTabItemFlags
int ImGuiTabItemFlags
Definition: imgui.h:142
ImGuiTabItem
Definition: imgui_internal.h:1206
ImGuiCol_SeparatorHovered
@ ImGuiCol_SeparatorHovered
Definition: imgui.h:1017
ImGuiTreeNodeFlags_NavLeftJumpsBackHere
@ ImGuiTreeNodeFlags_NavLeftJumpsBackHere
Definition: imgui.h:767
ImGuiSelectableFlags_DrawFillAvailWidth
@ ImGuiSelectableFlags_DrawFillAvailWidth
Definition: imgui_internal.h:323
IM_COL32
#define IM_COL32(R, G, B, A)
Definition: imgui.h:1682
ImVector::back
T & back()
Definition: imgui.h:1196
ImGuiMouseCursor_ResizeNS
@ ImGuiMouseCursor_ResizeNS
Definition: imgui.h:1127
ImGuiInputTextState::TempBuffer
ImVector< char > TempBuffer
Definition: imgui_internal.h:527
ImFont::FallbackGlyph
const ImFontGlyph * FallbackGlyph
Definition: imgui.h:2080
ImGuiSelectableFlags_PressedOnRelease
@ ImGuiSelectableFlags_PressedOnRelease
Definition: imgui_internal.h:322
ImGui::GetScrollMaxY
IMGUI_API float GetScrollMaxY()
Definition: imgui.cpp:6267
ImGuiContext::HoveredWindow
ImGuiWindow * HoveredWindow
Definition: imgui_internal.h:739
ImGui::EndChildFrame
IMGUI_API void EndChildFrame()
Definition: imgui.cpp:4353
ImRect::GetTR
ImVec2 GetTR() const
Definition: imgui_internal.h:456
ImGui::GetColorU32
IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul=1.0f)
Definition: imgui.cpp:1784
ImTextCharFromUtf8
int ImTextCharFromUtf8(unsigned int *out_char, const char *in_text, const char *in_text_end)
Definition: imgui.cpp:1532
ImFont::Glyphs
ImVector< ImFontGlyph > Glyphs
Definition: imgui.h:2077
t
geometry_msgs::TransformStamped t
ImGuiTabBar::ScrollingAnim
float ScrollingAnim
Definition: imgui_internal.h:1233
ImGui::EndMenu
IMGUI_API void EndMenu()
Definition: imgui_widgets.cpp:5693
ImGuiButtonFlags_DontClosePopups
@ ImGuiButtonFlags_DontClosePopups
Definition: imgui_internal.h:285
ImGuiContext::TabSortByWidthBuffer
ImVector< ImGuiTabBarSortItem > TabSortByWidthBuffer
Definition: imgui_internal.h:840
ImFont::FallbackAdvanceX
float FallbackAdvanceX
Definition: imgui.h:2081
ImGui::PlotLines
IMGUI_API void PlotLines(const char *label, const float *values, int values_count, int values_offset=0, const char *overlay_text=NULL, float scale_min=FLT_MAX, float scale_max=FLT_MAX, ImVec2 graph_size=ImVec2(0, 0), int stride=sizeof(float))
Definition: imgui_widgets.cpp:5343
ImGuiInputTextCallbackData::SelectionEnd
int SelectionEnd
Definition: imgui.h:1429
ImParseFormatFindEnd
const char * ImParseFormatFindEnd(const char *fmt)
Definition: imgui_widgets.cpp:2549
ImGui::PopFont
IMGUI_API void PopFont()
Definition: imgui.cpp:5563
ImGui::EndPopup
IMGUI_API void EndPopup()
Definition: imgui.cpp:6817
ImGuiKey_Tab
@ ImGuiKey_Tab
Definition: imgui.h:902
ImGui::KeepAliveID
IMGUI_API void KeepAliveID(ImGuiID id)
Definition: imgui.cpp:2637
ImGui::BulletText
IMGUI_API void BulletText(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui_widgets.cpp:327
ImGuiContext::NavInputId
ImGuiID NavInputId
Definition: imgui_internal.h:779
ImGui::InputFloat
IMGUI_API bool InputFloat(const char *label, float *v, float step=0.0f, float step_fast=0.0f, const char *format="%.3f", ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2729
ImGuiTabItem::ID
ImGuiID ID
Definition: imgui_internal.h:1208
ImGuiCol_CheckMark
@ ImGuiCol_CheckMark
Definition: imgui.h:1007
ImDrawList::PathStroke
void PathStroke(ImU32 col, bool closed, float thickness=1.0f)
Definition: imgui.h:1844
ImGuiButtonFlags_PressedOnDoubleClick
@ ImGuiButtonFlags_PressedOnDoubleClick
Definition: imgui_internal.h:282
ImVec2::y
float y
Definition: imgui.h:166
ImGui::TabBarRemoveTab
IMGUI_API void TabBarRemoveTab(ImGuiTabBar *tab_bar, ImGuiID tab_id)
Definition: imgui_widgets.cpp:6099
ImGuiItemFlags_SelectableDontClosePopup
@ ImGuiItemFlags_SelectableDontClosePopup
Definition: imgui_internal.h:996
ImGuiIO::SetClipboardTextFn
void(* SetClipboardTextFn)(void *user_data, const char *text)
Definition: imgui.h:1320
StbTexteditRow::ymax
float ymax
Definition: imstb_textedit.h:364
ImGuiStyle::ButtonTextAlign
ImVec2 ButtonTextAlign
Definition: imgui.h:1250
ImFont::DisplayOffset
ImVec2 DisplayOffset
Definition: imgui.h:2076
ImGuiTreeNodeFlags_CollapsingHeader
@ ImGuiTreeNodeFlags_CollapsingHeader
Definition: imgui.h:768
ImGuiContext::NavActivateId
ImGuiID NavActivateId
Definition: imgui_internal.h:776
ImGuiTreeNodeFlags_OpenOnArrow
@ ImGuiTreeNodeFlags_OpenOnArrow
Definition: imgui.h:761
ImGui::FocusableItemRegister
IMGUI_API bool FocusableItemRegister(ImGuiWindow *window, ImGuiID id, bool tab_stop=true)
Definition: imgui.cpp:2830
ImGuiSeparatorFlags_Vertical
@ ImGuiSeparatorFlags_Vertical
Definition: imgui_internal.h:330
ImGui::NewLine
IMGUI_API void NewLine()
Definition: imgui_widgets.cpp:1101
ImGui::TabBarLayout
static void TabBarLayout(ImGuiTabBar *tab_bar)
Definition: imgui_widgets.cpp:5913
ImGuiComboFlags_HeightLarge
@ ImGuiComboFlags_HeightLarge
Definition: imgui.h:793
ImGuiMenuColumns::NextWidth
float NextWidth
Definition: imgui_internal.h:512
ImGui::BeginChildFrame
IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2 &size, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:4339
ImGuiContext::DragCurrentAccum
float DragCurrentAccum
Definition: imgui_internal.h:849
ImGui::Image
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &uv0=ImVec2(0, 0), const ImVec2 &uv1=ImVec2(1, 1), const ImVec4 &tint_col=ImVec4(1, 1, 1, 1), const ImVec4 &border_col=ImVec4(0, 0, 0, 0))
Definition: imgui_widgets.cpp:812
ImGuiWindowTempData::LastItemRect
ImRect LastItemRect
Definition: imgui_internal.h:1017
ImGui::CloseButton
IMGUI_API bool CloseButton(ImGuiID id, const ImVec2 &pos, float radius)
Definition: imgui_widgets.cpp:651
ImGuiKey_V
@ ImGuiKey_V
Definition: imgui.h:919


mvsim
Author(s):
autogenerated on Wed May 28 2025 02:13:08