imgui_widgets.cpp
Go to the documentation of this file.
1 // dear imgui, v1.76 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 // [SECTION] Widgets: Columns, BeginColumns, EndColumns, etc.
28 
29 */
30 
31 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
32 #define _CRT_SECURE_NO_WARNINGS
33 #endif
34 
35 #include "imgui.h"
36 #ifndef IMGUI_DISABLE
37 
38 #ifndef IMGUI_DEFINE_MATH_OPERATORS
39 #define IMGUI_DEFINE_MATH_OPERATORS
40 #endif
41 #include "imgui_internal.h"
42 
43 #include <ctype.h> // toupper
44 #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
45 #include <stddef.h> // intptr_t
46 #else
47 #include <stdint.h> // intptr_t
48 #endif
49 
50 // Visual Studio warnings
51 #ifdef _MSC_VER
52 #pragma warning (disable: 4127) // condition expression is constant
53 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
54 #if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
55 #pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
56 #endif
57 #endif
58 
59 // Clang/GCC warnings with -Weverything
60 #if defined(__clang__)
61 #pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
62 #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
63 #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
64 #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
65 #if __has_warning("-Wzero-as-null-pointer-constant")
66 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning : zero as null pointer constant // some standard header variations use #define NULL 0
67 #endif
68 #if __has_warning("-Wdouble-promotion")
69 #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
70 #endif
71 #if __has_warning("-Wdeprecated-enum-enum-conversion")
72 #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
73 #endif
74 #elif defined(__GNUC__)
75 #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
76 #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
77 #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
78 #endif
79 
80 //-------------------------------------------------------------------------
81 // Data
82 //-------------------------------------------------------------------------
83 
84 // Those MIN/MAX values are not define because we need to point to them
85 static const signed char IM_S8_MIN = -128;
86 static const signed char IM_S8_MAX = 127;
87 static const unsigned char IM_U8_MIN = 0;
88 static const unsigned char IM_U8_MAX = 0xFF;
89 static const signed short IM_S16_MIN = -32768;
90 static const signed short IM_S16_MAX = 32767;
91 static const unsigned short IM_U16_MIN = 0;
92 static const unsigned short IM_U16_MAX = 0xFFFF;
93 static const ImS32 IM_S32_MIN = INT_MIN; // (-2147483647 - 1), (0x80000000);
94 static const ImS32 IM_S32_MAX = INT_MAX; // (2147483647), (0x7FFFFFFF)
95 static const ImU32 IM_U32_MIN = 0;
96 static const ImU32 IM_U32_MAX = UINT_MAX; // (0xFFFFFFFF)
97 #ifdef LLONG_MIN
98 static const ImS64 IM_S64_MIN = LLONG_MIN; // (-9223372036854775807ll - 1ll);
99 static const ImS64 IM_S64_MAX = LLONG_MAX; // (9223372036854775807ll);
100 #else
101 static const ImS64 IM_S64_MIN = -9223372036854775807LL - 1;
102 static const ImS64 IM_S64_MAX = 9223372036854775807LL;
103 #endif
104 static const ImU64 IM_U64_MIN = 0;
105 #ifdef ULLONG_MAX
106 static const ImU64 IM_U64_MAX = ULLONG_MAX; // (0xFFFFFFFFFFFFFFFFull);
107 #else
108 static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1);
109 #endif
110 
111 //-------------------------------------------------------------------------
112 // [SECTION] Forward Declarations
113 //-------------------------------------------------------------------------
114 
115 // For InputTextEx()
116 static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data);
117 static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
118 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);
119 
120 //-------------------------------------------------------------------------
121 // [SECTION] Widgets: Text, etc.
122 //-------------------------------------------------------------------------
123 // - TextEx() [Internal]
124 // - TextUnformatted()
125 // - Text()
126 // - TextV()
127 // - TextColored()
128 // - TextColoredV()
129 // - TextDisabled()
130 // - TextDisabledV()
131 // - TextWrapped()
132 // - TextWrappedV()
133 // - LabelText()
134 // - LabelTextV()
135 // - BulletText()
136 // - BulletTextV()
137 //-------------------------------------------------------------------------
138 
139 void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
140 {
141  ImGuiWindow* window = GetCurrentWindow();
142  if (window->SkipItems)
143  return;
144 
145  ImGuiContext& g = *GImGui;
146  IM_ASSERT(text != NULL);
147  const char* text_begin = text;
148  if (text_end == NULL)
149  text_end = text + strlen(text); // FIXME-OPT
150 
151  const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
152  const float wrap_pos_x = window->DC.TextWrapPos;
153  const bool wrap_enabled = (wrap_pos_x >= 0.0f);
154  if (text_end - text > 2000 && !wrap_enabled)
155  {
156  // Long text!
157  // Perform manual coarse clipping to optimize for long multi-line text
158  // - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
159  // - 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.
160  // - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop.
161  const char* line = text;
162  const float line_height = GetTextLineHeight();
163  ImVec2 text_size(0,0);
164 
165  // Lines to skip (can't skip when logging text)
166  ImVec2 pos = text_pos;
167  if (!g.LogEnabled)
168  {
169  int lines_skippable = (int)((window->ClipRect.Min.y - text_pos.y) / line_height);
170  if (lines_skippable > 0)
171  {
172  int lines_skipped = 0;
173  while (line < text_end && lines_skipped < lines_skippable)
174  {
175  const char* line_end = (const char*)memchr(line, '\n', text_end - line);
176  if (!line_end)
177  line_end = text_end;
179  text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
180  line = line_end + 1;
181  lines_skipped++;
182  }
183  pos.y += lines_skipped * line_height;
184  }
185  }
186 
187  // Lines to render
188  if (line < text_end)
189  {
190  ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
191  while (line < text_end)
192  {
193  if (IsClippedEx(line_rect, 0, false))
194  break;
195 
196  const char* line_end = (const char*)memchr(line, '\n', text_end - line);
197  if (!line_end)
198  line_end = text_end;
199  text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
200  RenderText(pos, line, line_end, false);
201  line = line_end + 1;
202  line_rect.Min.y += line_height;
203  line_rect.Max.y += line_height;
204  pos.y += line_height;
205  }
206 
207  // Count remaining lines
208  int lines_skipped = 0;
209  while (line < text_end)
210  {
211  const char* line_end = (const char*)memchr(line, '\n', text_end - line);
212  if (!line_end)
213  line_end = text_end;
215  text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
216  line = line_end + 1;
217  lines_skipped++;
218  }
219  pos.y += lines_skipped * line_height;
220  }
221  text_size.y = (pos - text_pos).y;
222 
223  ImRect bb(text_pos, text_pos + text_size);
224  ItemSize(text_size, 0.0f);
225  ItemAdd(bb, 0);
226  }
227  else
228  {
229  const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
230  const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
231 
232  ImRect bb(text_pos, text_pos + text_size);
233  ItemSize(text_size, 0.0f);
234  if (!ItemAdd(bb, 0))
235  return;
236 
237  // Render (we don't hide text after ## in this end-user function)
238  RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
239  }
240 }
241 
242 void ImGui::TextUnformatted(const char* text, const char* text_end)
243 {
245 }
246 
247 void ImGui::Text(const char* fmt, ...)
248 {
249  va_list args;
250  va_start(args, fmt);
251  TextV(fmt, args);
252  va_end(args);
253 }
254 
255 void ImGui::TextV(const char* fmt, va_list args)
256 {
257  ImGuiWindow* window = GetCurrentWindow();
258  if (window->SkipItems)
259  return;
260 
261  ImGuiContext& g = *GImGui;
262  const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
263  TextEx(g.TempBuffer, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
264 }
265 
266 void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
267 {
268  va_list args;
269  va_start(args, fmt);
270  TextColoredV(col, fmt, args);
271  va_end(args);
272 }
273 
274 void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
275 {
277  TextV(fmt, args);
278  PopStyleColor();
279 }
280 
281 void ImGui::TextDisabled(const char* fmt, ...)
282 {
283  va_list args;
284  va_start(args, fmt);
286  va_end(args);
287 }
288 
289 void ImGui::TextDisabledV(const char* fmt, va_list args)
290 {
292  TextV(fmt, args);
293  PopStyleColor();
294 }
295 
296 void ImGui::TextWrapped(const char* fmt, ...)
297 {
298  va_list args;
299  va_start(args, fmt);
301  va_end(args);
302 }
303 
304 void ImGui::TextWrappedV(const char* fmt, va_list args)
305 {
306  ImGuiWindow* window = GetCurrentWindow();
307  bool need_backup = (window->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
308  if (need_backup)
309  PushTextWrapPos(0.0f);
310  TextV(fmt, args);
311  if (need_backup)
312  PopTextWrapPos();
313 }
314 
315 void ImGui::LabelText(const char* label, const char* fmt, ...)
316 {
317  va_list args;
318  va_start(args, fmt);
320  va_end(args);
321 }
322 
323 // Add a label+text combo aligned to other label+value widgets
324 void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
325 {
326  ImGuiWindow* window = GetCurrentWindow();
327  if (window->SkipItems)
328  return;
329 
330  ImGuiContext& g = *GImGui;
331  const ImGuiStyle& style = g.Style;
332  const float w = CalcItemWidth();
333 
334  const ImVec2 label_size = CalcTextSize(label, NULL, true);
335  const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
336  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);
337  ItemSize(total_bb, style.FramePadding.y);
338  if (!ItemAdd(total_bb, 0))
339  return;
340 
341  // Render
342  const char* value_text_begin = &g.TempBuffer[0];
343  const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
344  RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f));
345  if (label_size.x > 0.0f)
346  RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
347 }
348 
349 void ImGui::BulletText(const char* fmt, ...)
350 {
351  va_list args;
352  va_start(args, fmt);
353  BulletTextV(fmt, args);
354  va_end(args);
355 }
356 
357 // Text with a little bullet aligned to the typical tree node.
358 void ImGui::BulletTextV(const char* fmt, va_list args)
359 {
360  ImGuiWindow* window = GetCurrentWindow();
361  if (window->SkipItems)
362  return;
363 
364  ImGuiContext& g = *GImGui;
365  const ImGuiStyle& style = g.Style;
366 
367  const char* text_begin = g.TempBuffer;
368  const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
369  const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
370  const ImVec2 total_size = ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y); // Empty text doesn't add padding
371  ImVec2 pos = window->DC.CursorPos;
372  pos.y += window->DC.CurrLineTextBaseOffset;
373  ItemSize(total_size, 0.0f);
374  const ImRect bb(pos, pos + total_size);
375  if (!ItemAdd(bb, 0))
376  return;
377 
378  // Render
379  ImU32 text_col = GetColorU32(ImGuiCol_Text);
380  RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, g.FontSize*0.5f), text_col);
381  RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false);
382 }
383 
384 //-------------------------------------------------------------------------
385 // [SECTION] Widgets: Main
386 //-------------------------------------------------------------------------
387 // - ButtonBehavior() [Internal]
388 // - Button()
389 // - SmallButton()
390 // - InvisibleButton()
391 // - ArrowButton()
392 // - CloseButton() [Internal]
393 // - CollapseButton() [Internal]
394 // - ScrollbarEx() [Internal]
395 // - Scrollbar() [Internal]
396 // - Image()
397 // - ImageButton()
398 // - Checkbox()
399 // - CheckboxFlags()
400 // - RadioButton()
401 // - ProgressBar()
402 // - Bullet()
403 //-------------------------------------------------------------------------
404 
405 // The ButtonBehavior() function is key to many interactions and used by many/most widgets.
406 // Because we handle so many cases (keyboard/gamepad navigation, drag and drop) and many specific behavior (via ImGuiButtonFlags_),
407 // this code is a little complex.
408 // By far the most common path is interacting with the Mouse using the default ImGuiButtonFlags_PressedOnClickRelease button behavior.
409 // See the series of events below and the corresponding state reported by dear imgui:
410 //------------------------------------------------------------------------------------------------------------------------------------------------
411 // with PressedOnClickRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
412 // Frame N+0 (mouse is outside bb) - - - - - -
413 // Frame N+1 (mouse moves inside bb) - true - - - -
414 // Frame N+2 (mouse button is down) - true true true - true
415 // Frame N+3 (mouse button is down) - true true - - -
416 // Frame N+4 (mouse moves outside bb) - - true - - -
417 // Frame N+5 (mouse moves inside bb) - true true - - -
418 // Frame N+6 (mouse button is released) true true - - true -
419 // Frame N+7 (mouse button is released) - true - - - -
420 // Frame N+8 (mouse moves outside bb) - - - - - -
421 //------------------------------------------------------------------------------------------------------------------------------------------------
422 // with PressedOnClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
423 // Frame N+2 (mouse button is down) true true true true - true
424 // Frame N+3 (mouse button is down) - true true - - -
425 // Frame N+6 (mouse button is released) - true - - true -
426 // Frame N+7 (mouse button is released) - true - - - -
427 //------------------------------------------------------------------------------------------------------------------------------------------------
428 // with PressedOnRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
429 // Frame N+2 (mouse button is down) - true - - - true
430 // Frame N+3 (mouse button is down) - true - - - -
431 // Frame N+6 (mouse button is released) true true - - - -
432 // Frame N+7 (mouse button is released) - true - - - -
433 //------------------------------------------------------------------------------------------------------------------------------------------------
434 // with PressedOnDoubleClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
435 // Frame N+0 (mouse button is down) - true - - - true
436 // Frame N+1 (mouse button is down) - true - - - -
437 // Frame N+2 (mouse button is released) - true - - - -
438 // Frame N+3 (mouse button is released) - true - - - -
439 // Frame N+4 (mouse button is down) true true true true - true
440 // Frame N+5 (mouse button is down) - true true - - -
441 // Frame N+6 (mouse button is released) - true - - true -
442 // Frame N+7 (mouse button is released) - true - - - -
443 //------------------------------------------------------------------------------------------------------------------------------------------------
444 // Note that some combinations are supported,
445 // - PressedOnDragDropHold can generally be associated with any flag.
446 // - PressedOnDoubleClick can be associated by PressedOnClickRelease/PressedOnRelease, in which case the second release event won't be reported.
447 //------------------------------------------------------------------------------------------------------------------------------------------------
448 // The behavior of the return-value changes when ImGuiButtonFlags_Repeat is set:
449 // Repeat+ Repeat+ Repeat+ Repeat+
450 // PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick
451 //-------------------------------------------------------------------------------------------------------------------------------------------------
452 // Frame N+0 (mouse button is down) - true - true
453 // ... - - - -
454 // Frame N + RepeatDelay true true - true
455 // ... - - - -
456 // Frame N + RepeatDelay + RepeatRate*N true true - true
457 //-------------------------------------------------------------------------------------------------------------------------------------------------
458 
459 bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
460 {
461  ImGuiContext& g = *GImGui;
462  ImGuiWindow* window = GetCurrentWindow();
463 
465  {
466  if (out_hovered) *out_hovered = false;
467  if (out_held) *out_held = false;
468  if (g.ActiveId == id) ClearActiveID();
469  return false;
470  }
471 
472  // Default only reacts to left mouse button
475 
476  // Default behavior requires click + release inside bounding box
479 
480  ImGuiWindow* backup_hovered_window = g.HoveredWindow;
481  const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window;
482  if (flatten_hovered_children)
483  g.HoveredWindow = window;
484 
485 #ifdef IMGUI_ENABLE_TEST_ENGINE
486  if (id != 0 && window->DC.LastItemId != id)
487  ImGuiTestEngineHook_ItemAdd(&g, bb, id);
488 #endif
489 
490  bool pressed = false;
491  bool hovered = ItemHoverable(bb, id);
492 
493  // Drag source doesn't report as hovered
494  if (hovered && g.DragDropActive && g.DragDropPayload.SourceId == id && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover))
495  hovered = false;
496 
497  // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button
498  if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
500  {
501  hovered = true;
502  SetHoveredID(id);
503  if (CalcTypematicRepeatAmount(g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, g.HoveredIdTimer + 0.0001f, 0.70f, 0.00f))
504  {
505  pressed = true;
506  FocusWindow(window);
507  }
508  }
509 
510  if (flatten_hovered_children)
511  g.HoveredWindow = backup_hovered_window;
512 
513  // 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.
514  if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0))
515  hovered = false;
516 
517  // Mouse handling
518  if (hovered)
519  {
520  if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
521  {
522  // Poll buttons
523  int mouse_button_clicked = -1;
524  int mouse_button_released = -1;
525  if ((flags & ImGuiButtonFlags_MouseButtonLeft) && g.IO.MouseClicked[0]) { mouse_button_clicked = 0; }
526  else if ((flags & ImGuiButtonFlags_MouseButtonRight) && g.IO.MouseClicked[1]) { mouse_button_clicked = 1; }
527  else if ((flags & ImGuiButtonFlags_MouseButtonMiddle) && g.IO.MouseClicked[2]) { mouse_button_clicked = 2; }
528  if ((flags & ImGuiButtonFlags_MouseButtonLeft) && g.IO.MouseReleased[0]) { mouse_button_released = 0; }
529  else if ((flags & ImGuiButtonFlags_MouseButtonRight) && g.IO.MouseReleased[1]) { mouse_button_released = 1; }
530  else if ((flags & ImGuiButtonFlags_MouseButtonMiddle) && g.IO.MouseReleased[2]) { mouse_button_released = 2; }
531 
532  if (mouse_button_clicked != -1 && g.ActiveId != id)
533  {
535  {
536  SetActiveID(id, window);
537  g.ActiveIdMouseButton = mouse_button_clicked;
539  SetFocusID(id, window);
540  FocusWindow(window);
541  }
542  if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[mouse_button_clicked]))
543  {
544  pressed = true;
546  ClearActiveID();
547  else
548  SetActiveID(id, window); // Hold on ID
549  g.ActiveIdMouseButton = mouse_button_clicked;
550  FocusWindow(window);
551  }
552  }
553  if ((flags & ImGuiButtonFlags_PressedOnRelease) && mouse_button_released != -1)
554  {
555  // Repeat mode trumps on release behavior
556  if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay))
557  pressed = true;
558  ClearActiveID();
559  }
560 
561  // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above).
562  // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings.
563  if (g.ActiveId == id && (flags & ImGuiButtonFlags_Repeat))
564  if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, true))
565  pressed = true;
566  }
567 
568  if (pressed)
569  g.NavDisableHighlight = true;
570  }
571 
572  // Gamepad/Keyboard navigation
573  // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse.
574  if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId))
576  hovered = true;
577  if (g.NavActivateDownId == id)
578  {
579  bool nav_activated_by_code = (g.NavActivateId == id);
581  if (nav_activated_by_code || nav_activated_by_inputs)
582  pressed = true;
583  if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id)
584  {
585  // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
586  g.NavActivateId = id; // This is so SetActiveId assign a Nav source
587  SetActiveID(id, window);
588  if ((nav_activated_by_code || nav_activated_by_inputs) && !(flags & ImGuiButtonFlags_NoNavFocus))
589  SetFocusID(id, window);
590  }
591  }
592 
593  bool held = false;
594  if (g.ActiveId == id)
595  {
596  if (g.ActiveIdSource == ImGuiInputSource_Mouse)
597  {
598  if (g.ActiveIdIsJustActivated)
599  g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
600 
601  const int mouse_button = g.ActiveIdMouseButton;
602  IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT);
603  if (g.IO.MouseDown[mouse_button])
604  {
605  held = true;
606  }
607  else
608  {
609  bool release_in = hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease) != 0;
610  bool release_anywhere = (flags & ImGuiButtonFlags_PressedOnClickReleaseAnywhere) != 0;
611  if ((release_in || release_anywhere) && !g.DragDropActive)
612  {
613  bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDownWasDoubleClick[mouse_button];
614  bool is_repeating_already = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button] >= g.IO.KeyRepeatDelay; // Repeat mode trumps <on release>
615  if (!is_double_click_release && !is_repeating_already)
616  pressed = true;
617  }
618  ClearActiveID();
619  }
621  g.NavDisableHighlight = true;
622  }
623  else if (g.ActiveIdSource == ImGuiInputSource_Nav)
624  {
625  if (g.NavActivateDownId != id)
626  ClearActiveID();
627  }
628  if (pressed)
629  g.ActiveIdHasBeenPressedBefore = true;
630  }
631 
632  if (out_hovered) *out_hovered = hovered;
633  if (out_held) *out_held = held;
634 
635  return pressed;
636 }
637 
638 bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags)
639 {
640  ImGuiWindow* window = GetCurrentWindow();
641  if (window->SkipItems)
642  return false;
643 
644  ImGuiContext& g = *GImGui;
645  const ImGuiStyle& style = g.Style;
646  const ImGuiID id = window->GetID(label);
647  const ImVec2 label_size = CalcTextSize(label, NULL, true);
648 
649  ImVec2 pos = window->DC.CursorPos;
650  if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // 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)
651  pos.y += window->DC.CurrLineTextBaseOffset - style.FramePadding.y;
652  ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
653 
654  const ImRect bb(pos, pos + size);
655  ItemSize(size, style.FramePadding.y);
656  if (!ItemAdd(bb, id))
657  return false;
658 
661  bool hovered, held;
662  bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
663 
664  // Render
665  const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
666  RenderNavHighlight(bb, id);
667  RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
668  RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
669 
670  // Automatically close popups
671  //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
672  // CloseCurrentPopup();
673 
675  return pressed;
676 }
677 
678 bool ImGui::Button(const char* label, const ImVec2& size_arg)
679 {
680  return ButtonEx(label, size_arg, 0);
681 }
682 
683 // Small buttons fits within text without additional vertical spacing.
684 bool ImGui::SmallButton(const char* label)
685 {
686  ImGuiContext& g = *GImGui;
687  float backup_padding_y = g.Style.FramePadding.y;
688  g.Style.FramePadding.y = 0.0f;
690  g.Style.FramePadding.y = backup_padding_y;
691  return pressed;
692 }
693 
694 // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack.
695 // 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)
696 bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg)
697 {
698  ImGuiWindow* window = GetCurrentWindow();
699  if (window->SkipItems)
700  return false;
701 
702  // Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size.
703  IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f);
704 
705  const ImGuiID id = window->GetID(str_id);
706  ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
707  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
708  ItemSize(size);
709  if (!ItemAdd(bb, id))
710  return false;
711 
712  bool hovered, held;
713  bool pressed = ButtonBehavior(bb, id, &hovered, &held);
714 
715  return pressed;
716 }
717 
719 {
720  ImGuiWindow* window = GetCurrentWindow();
721  if (window->SkipItems)
722  return false;
723 
724  ImGuiContext& g = *GImGui;
725  const ImGuiID id = window->GetID(str_id);
726  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
727  const float default_size = GetFrameHeight();
728  ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : -1.0f);
729  if (!ItemAdd(bb, id))
730  return false;
731 
734 
735  bool hovered, held;
736  bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
737 
738  // Render
739  const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
740  const ImU32 text_col = GetColorU32(ImGuiCol_Text);
741  RenderNavHighlight(bb, id);
742  RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
743  RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), text_col, dir);
744 
745  return pressed;
746 }
747 
748 bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir)
749 {
750  float sz = GetFrameHeight();
751  return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), ImGuiButtonFlags_None);
752 }
753 
754 // Button to close a window
755 bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)//, float size)
756 {
757  ImGuiContext& g = *GImGui;
758  ImGuiWindow* window = g.CurrentWindow;
759 
760  // We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window.
761  // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
762  const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
763  bool is_clipped = !ItemAdd(bb, id);
764 
765  bool hovered, held;
766  bool pressed = ButtonBehavior(bb, id, &hovered, &held);
767  if (is_clipped)
768  return pressed;
769 
770  // Render
772  ImVec2 center = bb.GetCenter();
773  if (hovered)
774  window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12);
775 
776  float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
777  ImU32 cross_col = GetColorU32(ImGuiCol_Text);
778  center -= ImVec2(0.5f, 0.5f);
779  window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), cross_col, 1.0f);
780  window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), cross_col, 1.0f);
781 
782  return pressed;
783 }
784 
786 {
787  ImGuiContext& g = *GImGui;
788  ImGuiWindow* window = g.CurrentWindow;
789 
790  ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
791  ItemAdd(bb, id);
792  bool hovered, held;
793  bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None);
794 
795  // Render
796  ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
797  ImU32 text_col = GetColorU32(ImGuiCol_Text);
798  ImVec2 center = bb.GetCenter();
799  if (hovered || held)
800  window->DrawList->AddCircleFilled(center/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12);
801  RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f);
802 
803  // Switch to moving the window after mouse is moved beyond the initial drag threshold
804  if (IsItemActive() && IsMouseDragging(0))
805  StartMouseMovingWindow(window);
806 
807  return pressed;
808 }
809 
811 {
812  return window->GetIDNoKeepAlive(axis == ImGuiAxis_X ? "#SCROLLX" : "#SCROLLY");
813 }
814 
815 // Vertical/Horizontal scrollbar
816 // The entire piece of code below is rather confusing because:
817 // - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab)
818 // - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
819 // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
820 // Still, the code should probably be made simpler..
821 bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawCornerFlags rounding_corners)
822 {
823  ImGuiContext& g = *GImGui;
824  ImGuiWindow* window = g.CurrentWindow;
825  if (window->SkipItems)
826  return false;
827 
828  const float bb_frame_width = bb_frame.GetWidth();
829  const float bb_frame_height = bb_frame.GetHeight();
830  if (bb_frame_width <= 0.0f || bb_frame_height <= 0.0f)
831  return false;
832 
833  // When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the resize grab)
834  float alpha = 1.0f;
835  if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontSize + g.Style.FramePadding.y * 2.0f)
836  alpha = ImSaturate((bb_frame_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f));
837  if (alpha <= 0.0f)
838  return false;
839 
840  const ImGuiStyle& style = g.Style;
841  const bool allow_interaction = (alpha >= 1.0f);
842  const bool horizontal = (axis == ImGuiAxis_X);
843 
844  ImRect bb = bb_frame;
845  bb.Expand(ImVec2(-ImClamp(IM_FLOOR((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_FLOOR((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f)));
846 
847  // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar)
848  const float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight();
849 
850  // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount)
851  // But we maintain a minimum size in pixel to allow for the user to still aim inside.
852  IM_ASSERT(ImMax(size_contents_v, 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.
853  const float win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), 1.0f);
854  const float grab_h_pixels = ImClamp(scrollbar_size_v * (size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v);
855  const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
856 
857  // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
858  bool held = false;
859  bool hovered = false;
860  ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
861 
862  float scroll_max = ImMax(1.0f, size_contents_v - size_avail_v);
863  float scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
864  float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
865  if (held && allow_interaction && grab_h_norm < 1.0f)
866  {
867  float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y;
868  float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y;
869 
870  // Click position in scrollbar normalized space (0.0f->1.0f)
871  const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
872  SetHoveredID(id);
873 
874  bool seek_absolute = false;
875  if (g.ActiveIdIsJustActivated)
876  {
877  // On initial click calculate the distance between mouse and the center of the grab
878  seek_absolute = (clicked_v_norm < grab_v_norm || clicked_v_norm > grab_v_norm + grab_h_norm);
879  if (seek_absolute)
880  g.ScrollbarClickDeltaToGrabCenter = 0.0f;
881  else
882  g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
883  }
884 
885  // Apply scroll
886  // It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position
887  const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
888  *p_scroll_v = IM_ROUND(scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));
889 
890  // Update values for rendering
891  scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
892  grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
893 
894  // Update distance to grab now that we have seeked and saturated
895  if (seek_absolute)
896  g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
897  }
898 
899  // Render
900  window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, GetColorU32(ImGuiCol_ScrollbarBg), window->WindowRounding, rounding_corners);
902  ImRect grab_rect;
903  if (horizontal)
904  grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y);
905  else
906  grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels);
907  window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding);
908 
909  return held;
910 }
911 
913 {
914  ImGuiContext& g = *GImGui;
915  ImGuiWindow* window = g.CurrentWindow;
916 
917  const ImGuiID id = GetWindowScrollbarID(window, axis);
918  KeepAliveID(id);
919 
920  // Calculate scrollbar bounding box
921  const ImRect outer_rect = window->Rect();
922  const ImRect inner_rect = window->InnerRect;
923  const float border_size = window->WindowBorderSize;
924  const float scrollbar_size = window->ScrollbarSizes[axis ^ 1];
925  IM_ASSERT(scrollbar_size > 0.0f);
926  const float other_scrollbar_size = window->ScrollbarSizes[axis];
927  ImDrawCornerFlags rounding_corners = (other_scrollbar_size <= 0.0f) ? ImDrawCornerFlags_BotRight : 0;
928  ImRect bb;
929  if (axis == ImGuiAxis_X)
930  {
931  bb.Min = ImVec2(inner_rect.Min.x, ImMax(outer_rect.Min.y, outer_rect.Max.y - border_size - scrollbar_size));
932  bb.Max = ImVec2(inner_rect.Max.x, outer_rect.Max.y);
933  rounding_corners |= ImDrawCornerFlags_BotLeft;
934  }
935  else
936  {
937  bb.Min = ImVec2(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y);
938  bb.Max = ImVec2(outer_rect.Max.x, window->InnerRect.Max.y);
939  rounding_corners |= ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0;
940  }
941  ScrollbarEx(bb, id, axis, &window->Scroll[axis], inner_rect.Max[axis] - inner_rect.Min[axis], window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f, rounding_corners);
942 }
943 
944 void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
945 {
946  ImGuiWindow* window = GetCurrentWindow();
947  if (window->SkipItems)
948  return;
949 
950  ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
951  if (border_col.w > 0.0f)
952  bb.Max += ImVec2(2, 2);
953  ItemSize(bb);
954  if (!ItemAdd(bb, 0))
955  return;
956 
957  if (border_col.w > 0.0f)
958  {
959  window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f);
960  window->DrawList->AddImage(user_texture_id, bb.Min + ImVec2(1, 1), bb.Max - ImVec2(1, 1), uv0, uv1, GetColorU32(tint_col));
961  }
962  else
963  {
964  window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col));
965  }
966 }
967 
968 // frame_padding < 0: uses FramePadding from style (default)
969 // frame_padding = 0: no framing
970 // frame_padding > 0: set framing size
971 // The color used are the button colors.
972 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)
973 {
974  ImGuiWindow* window = GetCurrentWindow();
975  if (window->SkipItems)
976  return false;
977 
978  ImGuiContext& g = *GImGui;
979  const ImGuiStyle& style = g.Style;
980 
981  // Default to using texture ID as ID. User can still push string/integer prefixes.
982  // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV.
983  PushID((void*)(intptr_t)user_texture_id);
984  const ImGuiID id = window->GetID("#image");
985  PopID();
986 
987  const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;
988  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2);
989  const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size);
990  ItemSize(bb);
991  if (!ItemAdd(bb, id))
992  return false;
993 
994  bool hovered, held;
995  bool pressed = ButtonBehavior(bb, id, &hovered, &held);
996 
997  // Render
998  const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
999  RenderNavHighlight(bb, id);
1000  RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding));
1001  if (bg_col.w > 0.0f)
1002  window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col));
1003  window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col));
1004 
1005  return pressed;
1006 }
1007 
1008 bool ImGui::Checkbox(const char* label, bool* v)
1009 {
1010  ImGuiWindow* window = GetCurrentWindow();
1011  if (window->SkipItems)
1012  return false;
1013 
1014  ImGuiContext& g = *GImGui;
1015  const ImGuiStyle& style = g.Style;
1016  const ImGuiID id = window->GetID(label);
1017  const ImVec2 label_size = CalcTextSize(label, NULL, true);
1018 
1019  const float square_sz = GetFrameHeight();
1020  const ImVec2 pos = window->DC.CursorPos;
1021  const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
1022  ItemSize(total_bb, style.FramePadding.y);
1023  if (!ItemAdd(total_bb, id))
1024  return false;
1025 
1026  bool hovered, held;
1027  bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
1028  if (pressed)
1029  {
1030  *v = !(*v);
1031  MarkItemEdited(id);
1032  }
1033 
1034  const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
1035  RenderNavHighlight(total_bb, id);
1036  RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
1037  ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
1038  if (window->DC.ItemFlags & ImGuiItemFlags_MixedValue)
1039  {
1040  // Undocumented tristate/mixed/indeterminate checkbox (#2644)
1041  ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)));
1042  window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding);
1043  }
1044  else if (*v)
1045  {
1046  const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
1047  RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad*2.0f);
1048  }
1049 
1050  if (g.LogEnabled)
1051  LogRenderedText(&total_bb.Min, *v ? "[x]" : "[ ]");
1052  if (label_size.x > 0.0f)
1053  RenderText(ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y), label);
1054 
1055  IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
1056  return pressed;
1057 }
1058 
1059 bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value)
1060 {
1061  bool v = ((*flags & flags_value) == flags_value);
1062  bool pressed = Checkbox(label, &v);
1063  if (pressed)
1064  {
1065  if (v)
1066  *flags |= flags_value;
1067  else
1068  *flags &= ~flags_value;
1069  }
1070 
1071  return pressed;
1072 }
1073 
1074 bool ImGui::RadioButton(const char* label, bool active)
1075 {
1076  ImGuiWindow* window = GetCurrentWindow();
1077  if (window->SkipItems)
1078  return false;
1079 
1080  ImGuiContext& g = *GImGui;
1081  const ImGuiStyle& style = g.Style;
1082  const ImGuiID id = window->GetID(label);
1083  const ImVec2 label_size = CalcTextSize(label, NULL, true);
1084 
1085  const float square_sz = GetFrameHeight();
1086  const ImVec2 pos = window->DC.CursorPos;
1087  const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
1088  const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
1089  ItemSize(total_bb, style.FramePadding.y);
1090  if (!ItemAdd(total_bb, id))
1091  return false;
1092 
1093  ImVec2 center = check_bb.GetCenter();
1094  center.x = IM_ROUND(center.x);
1095  center.y = IM_ROUND(center.y);
1096  const float radius = (square_sz - 1.0f) * 0.5f;
1097 
1098  bool hovered, held;
1099  bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
1100  if (pressed)
1101  MarkItemEdited(id);
1102 
1103  RenderNavHighlight(total_bb, id);
1104  window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
1105  if (active)
1106  {
1107  const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
1108  window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16);
1109  }
1110 
1111  if (style.FrameBorderSize > 0.0f)
1112  {
1113  window->DrawList->AddCircle(center + ImVec2(1,1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize);
1114  window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize);
1115  }
1116 
1117  if (g.LogEnabled)
1118  LogRenderedText(&total_bb.Min, active ? "(x)" : "( )");
1119  if (label_size.x > 0.0f)
1120  RenderText(ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y), label);
1121 
1122  return pressed;
1123 }
1124 
1125 // FIXME: This would work nicely if it was a public template, e.g. 'template<T> RadioButton(const char* label, T* v, T v_button)', but I'm not sure how we would expose it..
1126 bool ImGui::RadioButton(const char* label, int* v, int v_button)
1127 {
1128  const bool pressed = RadioButton(label, *v == v_button);
1129  if (pressed)
1130  *v = v_button;
1131  return pressed;
1132 }
1133 
1134 // size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size
1135 void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay)
1136 {
1137  ImGuiWindow* window = GetCurrentWindow();
1138  if (window->SkipItems)
1139  return;
1140 
1141  ImGuiContext& g = *GImGui;
1142  const ImGuiStyle& style = g.Style;
1143 
1144  ImVec2 pos = window->DC.CursorPos;
1145  ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f);
1146  ImRect bb(pos, pos + size);
1147  ItemSize(size, style.FramePadding.y);
1148  if (!ItemAdd(bb, 0))
1149  return;
1150 
1151  // Render
1152  fraction = ImSaturate(fraction);
1154  bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize));
1155  const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y);
1157 
1158  // Default displaying the fraction as percentage string, but user can override it
1159  char overlay_buf[32];
1160  if (!overlay)
1161  {
1162  ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction*100+0.01f);
1163  overlay = overlay_buf;
1164  }
1165 
1166  ImVec2 overlay_size = CalcTextSize(overlay, NULL);
1167  if (overlay_size.x > 0.0f)
1168  RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f,0.5f), &bb);
1169 }
1170 
1172 {
1173  ImGuiWindow* window = GetCurrentWindow();
1174  if (window->SkipItems)
1175  return;
1176 
1177  ImGuiContext& g = *GImGui;
1178  const ImGuiStyle& style = g.Style;
1179  const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
1180  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height));
1181  ItemSize(bb);
1182  if (!ItemAdd(bb, 0))
1183  {
1184  SameLine(0, style.FramePadding.x*2);
1185  return;
1186  }
1187 
1188  // Render and stay on same line
1189  ImU32 text_col = GetColorU32(ImGuiCol_Text);
1190  RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), text_col);
1191  SameLine(0, style.FramePadding.x * 2.0f);
1192 }
1193 
1194 //-------------------------------------------------------------------------
1195 // [SECTION] Widgets: Low-level Layout helpers
1196 //-------------------------------------------------------------------------
1197 // - Spacing()
1198 // - Dummy()
1199 // - NewLine()
1200 // - AlignTextToFramePadding()
1201 // - SeparatorEx() [Internal]
1202 // - Separator()
1203 // - SplitterBehavior() [Internal]
1204 // - ShrinkWidths() [Internal]
1205 //-------------------------------------------------------------------------
1206 
1208 {
1209  ImGuiWindow* window = GetCurrentWindow();
1210  if (window->SkipItems)
1211  return;
1212  ItemSize(ImVec2(0,0));
1213 }
1214 
1216 {
1217  ImGuiWindow* window = GetCurrentWindow();
1218  if (window->SkipItems)
1219  return;
1220 
1221  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
1222  ItemSize(size);
1223  ItemAdd(bb, 0);
1224 }
1225 
1227 {
1228  ImGuiWindow* window = GetCurrentWindow();
1229  if (window->SkipItems)
1230  return;
1231 
1232  ImGuiContext& g = *GImGui;
1233  const ImGuiLayoutType backup_layout_type = window->DC.LayoutType;
1235  if (window->DC.CurrLineSize.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.
1236  ItemSize(ImVec2(0,0));
1237  else
1238  ItemSize(ImVec2(0.0f, g.FontSize));
1239  window->DC.LayoutType = backup_layout_type;
1240 }
1241 
1243 {
1244  ImGuiWindow* window = GetCurrentWindow();
1245  if (window->SkipItems)
1246  return;
1247 
1248  ImGuiContext& g = *GImGui;
1249  window->DC.CurrLineSize.y = ImMax(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2);
1250  window->DC.CurrLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, g.Style.FramePadding.y);
1251 }
1252 
1253 // Horizontal/vertical separating line
1255 {
1256  ImGuiWindow* window = GetCurrentWindow();
1257  if (window->SkipItems)
1258  return;
1259 
1260  ImGuiContext& g = *GImGui;
1261  IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected
1262 
1263  float thickness_draw = 1.0f;
1264  float thickness_layout = 0.0f;
1266  {
1267  // Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout.
1268  float y1 = window->DC.CursorPos.y;
1269  float y2 = window->DC.CursorPos.y + window->DC.CurrLineSize.y;
1270  const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + thickness_draw, y2));
1271  ItemSize(ImVec2(thickness_layout, 0.0f));
1272  if (!ItemAdd(bb, 0))
1273  return;
1274 
1275  // Draw
1276  window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
1277  if (g.LogEnabled)
1278  LogText(" |");
1279  }
1281  {
1282  // Horizontal Separator
1283  float x1 = window->Pos.x;
1284  float x2 = window->Pos.x + window->Size.x;
1285  if (!window->DC.GroupStack.empty())
1286  x1 += window->DC.Indent.x;
1287 
1289  if (columns)
1291 
1292  // We don't provide our width to the layout so that it doesn't get feed back into AutoFit
1293  const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw));
1294  ItemSize(ImVec2(0.0f, thickness_layout));
1295  const bool item_visible = ItemAdd(bb, 0);
1296  if (item_visible)
1297  {
1298  // Draw
1299  window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Separator));
1300  if (g.LogEnabled)
1301  LogRenderedText(&bb.Min, "--------------------------------");
1302  }
1303  if (columns)
1304  {
1306  columns->LineMinY = window->DC.CursorPos.y;
1307  }
1308  }
1309 }
1310 
1312 {
1313  ImGuiContext& g = *GImGui;
1314  ImGuiWindow* window = g.CurrentWindow;
1315  if (window->SkipItems)
1316  return;
1317 
1318  // Those flags should eventually be overridable by the user
1321  SeparatorEx(flags);
1322 }
1323 
1324 // 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.
1325 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)
1326 {
1327  ImGuiContext& g = *GImGui;
1328  ImGuiWindow* window = g.CurrentWindow;
1329 
1330  const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
1332  bool item_add = ItemAdd(bb, id);
1333  window->DC.ItemFlags = item_flags_backup;
1334  if (!item_add)
1335  return false;
1336 
1337  bool hovered, held;
1338  ImRect bb_interact = bb;
1339  bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f));
1341  if (g.ActiveId != id)
1343 
1344  if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay))
1346 
1347  ImRect bb_render = bb;
1348  if (held)
1349  {
1350  ImVec2 mouse_delta_2d = g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min;
1351  float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x;
1352 
1353  // Minimum pane size
1354  float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1);
1355  float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2);
1356  if (mouse_delta < -size_1_maximum_delta)
1357  mouse_delta = -size_1_maximum_delta;
1358  if (mouse_delta > size_2_maximum_delta)
1359  mouse_delta = size_2_maximum_delta;
1360 
1361  // Apply resize
1362  if (mouse_delta != 0.0f)
1363  {
1364  if (mouse_delta < 0.0f)
1365  IM_ASSERT(*size1 + mouse_delta >= min_size1);
1366  if (mouse_delta > 0.0f)
1367  IM_ASSERT(*size2 - mouse_delta >= min_size2);
1368  *size1 += mouse_delta;
1369  *size2 -= mouse_delta;
1370  bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta));
1371  MarkItemEdited(id);
1372  }
1373  }
1374 
1375  // Render
1376  const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
1377  window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, 0.0f);
1378 
1379  return held;
1380 }
1381 
1382 static int IMGUI_CDECL ShrinkWidthItemComparer(const void* lhs, const void* rhs)
1383 {
1384  const ImGuiShrinkWidthItem* a = (const ImGuiShrinkWidthItem*)lhs;
1385  const ImGuiShrinkWidthItem* b = (const ImGuiShrinkWidthItem*)rhs;
1386  if (int d = (int)(b->Width - a->Width))
1387  return d;
1388  return (b->Index - a->Index);
1389 }
1390 
1391 // Shrink excess width from a set of item, by removing width from the larger items first.
1392 void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess)
1393 {
1394  if (count == 1)
1395  {
1396  items[0].Width = ImMax(items[0].Width - width_excess, 1.0f);
1397  return;
1398  }
1399  ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer);
1400  int count_same_width = 1;
1401  while (width_excess > 0.0f && count_same_width < count)
1402  {
1403  while (count_same_width < count && items[0].Width <= items[count_same_width].Width)
1404  count_same_width++;
1405  float max_width_to_remove_per_item = (count_same_width < count) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f);
1406  float width_to_remove_per_item = ImMin(width_excess / count_same_width, max_width_to_remove_per_item);
1407  for (int item_n = 0; item_n < count_same_width; item_n++)
1408  items[item_n].Width -= width_to_remove_per_item;
1409  width_excess -= width_to_remove_per_item * count_same_width;
1410  }
1411 
1412  // Round width and redistribute remainder left-to-right (could make it an option of the function?)
1413  // Ensure that e.g. the right-most tab of a shrunk tab-bar always reaches exactly at the same distance from the right-most edge of the tab bar separator.
1414  width_excess = 0.0f;
1415  for (int n = 0; n < count; n++)
1416  {
1417  float width_rounded = ImFloor(items[n].Width);
1418  width_excess += items[n].Width - width_rounded;
1419  items[n].Width = width_rounded;
1420  }
1421  if (width_excess > 0.0f)
1422  for (int n = 0; n < count; n++)
1423  if (items[n].Index < (int)(width_excess + 0.01f))
1424  items[n].Width += 1.0f;
1425 }
1426 
1427 //-------------------------------------------------------------------------
1428 // [SECTION] Widgets: ComboBox
1429 //-------------------------------------------------------------------------
1430 // - BeginCombo()
1431 // - EndCombo()
1432 // - Combo()
1433 //-------------------------------------------------------------------------
1434 
1435 static float CalcMaxPopupHeightFromItemCount(int items_count)
1436 {
1437  ImGuiContext& g = *GImGui;
1438  if (items_count <= 0)
1439  return FLT_MAX;
1440  return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2);
1441 }
1442 
1443 bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags)
1444 {
1445  // Always consume the SetNextWindowSizeConstraint() call in our early return paths
1446  ImGuiContext& g = *GImGui;
1447  bool has_window_size_constraint = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) != 0;
1449 
1450  ImGuiWindow* window = GetCurrentWindow();
1451  if (window->SkipItems)
1452  return false;
1453 
1455 
1456  const ImGuiStyle& style = g.Style;
1457  const ImGuiID id = window->GetID(label);
1458 
1459  const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
1460  const ImVec2 label_size = CalcTextSize(label, NULL, true);
1461  const float expected_w = CalcItemWidth();
1462  const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w;
1463  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
1464  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));
1465  ItemSize(total_bb, style.FramePadding.y);
1466  if (!ItemAdd(total_bb, id, &frame_bb))
1467  return false;
1468 
1469  bool hovered, held;
1470  bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);
1471  bool popup_open = IsPopupOpen(id);
1472 
1473  const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
1474  const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size);
1475  RenderNavHighlight(frame_bb, id);
1477  window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Left);
1479  {
1480  ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
1481  ImU32 text_col = GetColorU32(ImGuiCol_Text);
1482  window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right);
1483  if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x)
1484  RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
1485  }
1486  RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding);
1487  if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
1488  RenderTextClipped(frame_bb.Min + style.FramePadding, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f,0.0f));
1489  if (label_size.x > 0)
1490  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
1491 
1492  if ((pressed || g.NavActivateId == id) && !popup_open)
1493  {
1494  if (window->DC.NavLayerCurrent == 0)
1495  window->NavLastIds[0] = id;
1496  OpenPopupEx(id);
1497  popup_open = true;
1498  }
1499 
1500  if (!popup_open)
1501  return false;
1502 
1503  if (has_window_size_constraint)
1504  {
1505  g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
1506  g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w);
1507  }
1508  else
1509  {
1510  if ((flags & ImGuiComboFlags_HeightMask_) == 0)
1513  int popup_max_height_in_items = -1;
1514  if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
1515  else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
1516  else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
1517  SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
1518  }
1519 
1520  char name[16];
1521  ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
1522 
1523  // Peak into expected window size so we can position it
1524  if (ImGuiWindow* popup_window = FindWindowByName(name))
1525  if (popup_window->WasActive)
1526  {
1527  ImVec2 size_expected = CalcWindowExpectedSize(popup_window);
1529  popup_window->AutoPosLastDirection = ImGuiDir_Left;
1530  ImRect r_outer = GetWindowAllowedExtentRect(popup_window);
1531  ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox);
1532  SetNextWindowPos(pos);
1533  }
1534 
1535  // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx()
1537 
1538  // Horizontally align ourselves with the framed text
1540  bool ret = Begin(name, NULL, window_flags);
1541  PopStyleVar();
1542  if (!ret)
1543  {
1544  EndPopup();
1545  IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
1546  return false;
1547  }
1548  return true;
1549 }
1550 
1552 {
1553  EndPopup();
1554 }
1555 
1556 // Getter for the old Combo() API: const char*[]
1557 static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
1558 {
1559  const char* const* items = (const char* const*)data;
1560  if (out_text)
1561  *out_text = items[idx];
1562  return true;
1563 }
1564 
1565 // Getter for the old Combo() API: "item1\0item2\0item3\0"
1566 static bool Items_SingleStringGetter(void* data, int idx, const char** out_text)
1567 {
1568  // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited.
1569  const char* items_separated_by_zeros = (const char*)data;
1570  int items_count = 0;
1571  const char* p = items_separated_by_zeros;
1572  while (*p)
1573  {
1574  if (idx == items_count)
1575  break;
1576  p += strlen(p) + 1;
1577  items_count++;
1578  }
1579  if (!*p)
1580  return false;
1581  if (out_text)
1582  *out_text = p;
1583  return true;
1584 }
1585 
1586 // Old API, prefer using BeginCombo() nowadays if you can.
1587 bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items)
1588 {
1589  ImGuiContext& g = *GImGui;
1590 
1591  // Call the getter to obtain the preview string which is a parameter to BeginCombo()
1592  const char* preview_value = NULL;
1593  if (*current_item >= 0 && *current_item < items_count)
1594  items_getter(data, *current_item, &preview_value);
1595 
1596  // 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.
1597  if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint))
1598  SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
1599 
1600  if (!BeginCombo(label, preview_value, ImGuiComboFlags_None))
1601  return false;
1602 
1603  // Display items
1604  // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
1605  bool value_changed = false;
1606  for (int i = 0; i < items_count; i++)
1607  {
1608  PushID((void*)(intptr_t)i);
1609  const bool item_selected = (i == *current_item);
1610  const char* item_text;
1611  if (!items_getter(data, i, &item_text))
1612  item_text = "*Unknown item*";
1613  if (Selectable(item_text, item_selected))
1614  {
1615  value_changed = true;
1616  *current_item = i;
1617  }
1618  if (item_selected)
1620  PopID();
1621  }
1622 
1623  EndCombo();
1624  return value_changed;
1625 }
1626 
1627 // Combo box helper allowing to pass an array of strings.
1628 bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items)
1629 {
1630  const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items);
1631  return value_changed;
1632 }
1633 
1634 // Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0"
1635 bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
1636 {
1637  int items_count = 0;
1638  const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open
1639  while (*p)
1640  {
1641  p += strlen(p) + 1;
1642  items_count++;
1643  }
1644  bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items);
1645  return value_changed;
1646 }
1647 
1648 //-------------------------------------------------------------------------
1649 // [SECTION] Data Type and Data Formatting Helpers [Internal]
1650 //-------------------------------------------------------------------------
1651 // - PatchFormatStringFloatToInt()
1652 // - DataTypeGetInfo()
1653 // - DataTypeFormatString()
1654 // - DataTypeApplyOp()
1655 // - DataTypeApplyOpFromText()
1656 // - GetMinimumStepAtDecimalPrecision
1657 // - RoundScalarWithFormat<>()
1658 //-------------------------------------------------------------------------
1659 
1661 {
1662  { sizeof(char), "%d", "%d" }, // ImGuiDataType_S8
1663  { sizeof(unsigned char), "%u", "%u" },
1664  { sizeof(short), "%d", "%d" }, // ImGuiDataType_S16
1665  { sizeof(unsigned short), "%u", "%u" },
1666  { sizeof(int), "%d", "%d" }, // ImGuiDataType_S32
1667  { sizeof(unsigned int), "%u", "%u" },
1668 #ifdef _MSC_VER
1669  { sizeof(ImS64), "%I64d","%I64d" }, // ImGuiDataType_S64
1670  { sizeof(ImU64), "%I64u","%I64u" },
1671 #else
1672  { sizeof(ImS64), "%lld", "%lld" }, // ImGuiDataType_S64
1673  { sizeof(ImU64), "%llu", "%llu" },
1674 #endif
1675  { sizeof(float), "%f", "%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg)
1676  { sizeof(double), "%f", "%lf" }, // ImGuiDataType_Double
1677 };
1679 
1680 // 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".
1681 // Even though we changed the compile-time default, we expect users to have carried %f around, which would break the display of DragInt() calls.
1682 // To honor backward compatibility we are rewriting the format string, unless IMGUI_DISABLE_OBSOLETE_FUNCTIONS is enabled. What could possibly go wrong?!
1683 static const char* PatchFormatStringFloatToInt(const char* fmt)
1684 {
1685  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.
1686  return "%d";
1687  const char* fmt_start = ImParseFormatFindStart(fmt); // Find % (if any, and ignore %%)
1688  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).
1689  if (fmt_end > fmt_start && fmt_end[-1] == 'f')
1690  {
1691 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1692  if (fmt_start == fmt && fmt_end[0] == 0)
1693  return "%d";
1694  ImGuiContext& g = *GImGui;
1695  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.
1696  return g.TempBuffer;
1697 #else
1698  IM_ASSERT(0 && "DragInt(): Invalid format string!"); // Old versions used a default parameter of "%.0f", please replace with e.g. "%d"
1699 #endif
1700  }
1701  return fmt;
1702 }
1703 
1705 {
1706  IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
1707  return &GDataTypeInfo[data_type];
1708 }
1709 
1710 int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format)
1711 {
1712  // Signedness doesn't matter when pushing integer arguments
1713  if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32)
1714  return ImFormatString(buf, buf_size, format, *(const ImU32*)p_data);
1715  if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
1716  return ImFormatString(buf, buf_size, format, *(const ImU64*)p_data);
1717  if (data_type == ImGuiDataType_Float)
1718  return ImFormatString(buf, buf_size, format, *(const float*)p_data);
1719  if (data_type == ImGuiDataType_Double)
1720  return ImFormatString(buf, buf_size, format, *(const double*)p_data);
1721  if (data_type == ImGuiDataType_S8)
1722  return ImFormatString(buf, buf_size, format, *(const ImS8*)p_data);
1723  if (data_type == ImGuiDataType_U8)
1724  return ImFormatString(buf, buf_size, format, *(const ImU8*)p_data);
1725  if (data_type == ImGuiDataType_S16)
1726  return ImFormatString(buf, buf_size, format, *(const ImS16*)p_data);
1727  if (data_type == ImGuiDataType_U16)
1728  return ImFormatString(buf, buf_size, format, *(const ImU16*)p_data);
1729  IM_ASSERT(0);
1730  return 0;
1731 }
1732 
1733 void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2)
1734 {
1735  IM_ASSERT(op == '+' || op == '-');
1736  switch (data_type)
1737  {
1738  case ImGuiDataType_S8:
1739  if (op == '+') { *(ImS8*)output = ImAddClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); }
1740  if (op == '-') { *(ImS8*)output = ImSubClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); }
1741  return;
1742  case ImGuiDataType_U8:
1743  if (op == '+') { *(ImU8*)output = ImAddClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); }
1744  if (op == '-') { *(ImU8*)output = ImSubClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); }
1745  return;
1746  case ImGuiDataType_S16:
1747  if (op == '+') { *(ImS16*)output = ImAddClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); }
1748  if (op == '-') { *(ImS16*)output = ImSubClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); }
1749  return;
1750  case ImGuiDataType_U16:
1751  if (op == '+') { *(ImU16*)output = ImAddClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); }
1752  if (op == '-') { *(ImU16*)output = ImSubClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); }
1753  return;
1754  case ImGuiDataType_S32:
1755  if (op == '+') { *(ImS32*)output = ImAddClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); }
1756  if (op == '-') { *(ImS32*)output = ImSubClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); }
1757  return;
1758  case ImGuiDataType_U32:
1759  if (op == '+') { *(ImU32*)output = ImAddClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); }
1760  if (op == '-') { *(ImU32*)output = ImSubClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); }
1761  return;
1762  case ImGuiDataType_S64:
1763  if (op == '+') { *(ImS64*)output = ImAddClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); }
1764  if (op == '-') { *(ImS64*)output = ImSubClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); }
1765  return;
1766  case ImGuiDataType_U64:
1767  if (op == '+') { *(ImU64*)output = ImAddClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); }
1768  if (op == '-') { *(ImU64*)output = ImSubClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); }
1769  return;
1770  case ImGuiDataType_Float:
1771  if (op == '+') { *(float*)output = *(const float*)arg1 + *(const float*)arg2; }
1772  if (op == '-') { *(float*)output = *(const float*)arg1 - *(const float*)arg2; }
1773  return;
1774  case ImGuiDataType_Double:
1775  if (op == '+') { *(double*)output = *(const double*)arg1 + *(const double*)arg2; }
1776  if (op == '-') { *(double*)output = *(const double*)arg1 - *(const double*)arg2; }
1777  return;
1778  case ImGuiDataType_COUNT: break;
1779  }
1780  IM_ASSERT(0);
1781 }
1782 
1783 // User can input math operators (e.g. +100) to edit a numerical values.
1784 // NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
1785 bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format)
1786 {
1787  while (ImCharIsBlankA(*buf))
1788  buf++;
1789 
1790  // We don't support '-' op because it would conflict with inputing negative value.
1791  // Instead you can use +-100 to subtract from an existing value
1792  char op = buf[0];
1793  if (op == '+' || op == '*' || op == '/')
1794  {
1795  buf++;
1796  while (ImCharIsBlankA(*buf))
1797  buf++;
1798  }
1799  else
1800  {
1801  op = 0;
1802  }
1803  if (!buf[0])
1804  return false;
1805 
1806  // Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all.
1807  IM_ASSERT(data_type < ImGuiDataType_COUNT);
1808  int data_backup[2];
1809  const ImGuiDataTypeInfo* type_info = ImGui::DataTypeGetInfo(data_type);
1810  IM_ASSERT(type_info->Size <= sizeof(data_backup));
1811  memcpy(data_backup, p_data, type_info->Size);
1812 
1813  if (format == NULL)
1814  format = type_info->ScanFmt;
1815 
1816  // FIXME-LEGACY: The aim is to remove those operators and write a proper expression evaluator at some point..
1817  int arg1i = 0;
1818  if (data_type == ImGuiDataType_S32)
1819  {
1820  int* v = (int*)p_data;
1821  int arg0i = *v;
1822  float arg1f = 0.0f;
1823  if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
1824  return false;
1825  // 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
1826  if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); } // Add (use "+-" to subtract)
1827  else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); } // Multiply
1828  else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); } // Divide
1829  else { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; } // Assign constant
1830  }
1831  else if (data_type == ImGuiDataType_Float)
1832  {
1833  // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
1834  format = "%f";
1835  float* v = (float*)p_data;
1836  float arg0f = *v, arg1f = 0.0f;
1837  if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
1838  return false;
1839  if (sscanf(buf, format, &arg1f) < 1)
1840  return false;
1841  if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
1842  else if (op == '*') { *v = arg0f * arg1f; } // Multiply
1843  else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
1844  else { *v = arg1f; } // Assign constant
1845  }
1846  else if (data_type == ImGuiDataType_Double)
1847  {
1848  format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis
1849  double* v = (double*)p_data;
1850  double arg0f = *v, arg1f = 0.0;
1851  if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
1852  return false;
1853  if (sscanf(buf, format, &arg1f) < 1)
1854  return false;
1855  if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
1856  else if (op == '*') { *v = arg0f * arg1f; } // Multiply
1857  else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
1858  else { *v = arg1f; } // Assign constant
1859  }
1860  else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
1861  {
1862  // All other types assign constant
1863  // We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future.
1864  sscanf(buf, format, p_data);
1865  }
1866  else
1867  {
1868  // Small types need a 32-bit buffer to receive the result from scanf()
1869  int v32;
1870  sscanf(buf, format, &v32);
1871  if (data_type == ImGuiDataType_S8)
1872  *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX);
1873  else if (data_type == ImGuiDataType_U8)
1874  *(ImU8*)p_data = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX);
1875  else if (data_type == ImGuiDataType_S16)
1876  *(ImS16*)p_data = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX);
1877  else if (data_type == ImGuiDataType_U16)
1878  *(ImU16*)p_data = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX);
1879  else
1880  IM_ASSERT(0);
1881  }
1882 
1883  return memcmp(data_backup, p_data, type_info->Size) != 0;
1884 }
1885 
1886 static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
1887 {
1888  static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f };
1889  if (decimal_precision < 0)
1890  return FLT_MIN;
1891  return (decimal_precision < IM_ARRAYSIZE(min_steps)) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision);
1892 }
1893 
1894 template<typename TYPE>
1895 static const char* ImAtoi(const char* src, TYPE* output)
1896 {
1897  int negative = 0;
1898  if (*src == '-') { negative = 1; src++; }
1899  if (*src == '+') { src++; }
1900  TYPE v = 0;
1901  while (*src >= '0' && *src <= '9')
1902  v = (v * 10) + (*src++ - '0');
1903  *output = negative ? -v : v;
1904  return src;
1905 }
1906 
1907 template<typename TYPE, typename SIGNEDTYPE>
1909 {
1910  const char* fmt_start = ImParseFormatFindStart(format);
1911  if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string
1912  return v;
1913  char v_str[64];
1914  ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v);
1915  const char* p = v_str;
1916  while (*p == ' ')
1917  p++;
1918  if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
1919  v = (TYPE)ImAtof(p);
1920  else
1921  ImAtoi(p, (SIGNEDTYPE*)&v);
1922  return v;
1923 }
1924 
1925 //-------------------------------------------------------------------------
1926 // [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc.
1927 //-------------------------------------------------------------------------
1928 // - DragBehaviorT<>() [Internal]
1929 // - DragBehavior() [Internal]
1930 // - DragScalar()
1931 // - DragScalarN()
1932 // - DragFloat()
1933 // - DragFloat2()
1934 // - DragFloat3()
1935 // - DragFloat4()
1936 // - DragFloatRange2()
1937 // - DragInt()
1938 // - DragInt2()
1939 // - DragInt3()
1940 // - DragInt4()
1941 // - DragIntRange2()
1942 //-------------------------------------------------------------------------
1943 
1944 // This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls)
1945 template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
1946 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)
1947 {
1948  ImGuiContext& g = *GImGui;
1950  const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
1951  const bool is_clamped = (v_min < v_max);
1952  const bool is_power = (power != 1.0f && is_decimal && is_clamped && (v_max - v_min < FLT_MAX));
1953  const bool is_locked = (v_min > v_max);
1954  if (is_locked)
1955  return false;
1956 
1957  // Default tweak speed
1958  if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX))
1959  v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio);
1960 
1961  // Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings
1962  float adjust_delta = 0.0f;
1963  if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && g.IO.MouseDragMaxDistanceSqr[0] > 1.0f*1.0f)
1964  {
1965  adjust_delta = g.IO.MouseDelta[axis];
1966  if (g.IO.KeyAlt)
1967  adjust_delta *= 1.0f / 100.0f;
1968  if (g.IO.KeyShift)
1969  adjust_delta *= 10.0f;
1970  }
1971  else if (g.ActiveIdSource == ImGuiInputSource_Nav)
1972  {
1973  int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
1975  v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
1976  }
1977  adjust_delta *= v_speed;
1978 
1979  // For vertical drag we currently assume that Up=higher value (like we do with vertical sliders). This may become a parameter.
1980  if (axis == ImGuiAxis_Y)
1981  adjust_delta = -adjust_delta;
1982 
1983  // Clear current value on activation
1984  // 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.
1985  bool is_just_activated = g.ActiveIdIsJustActivated;
1986  bool is_already_past_limits_and_pushing_outward = is_clamped && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f));
1987  bool is_drag_direction_change_with_power = is_power && ((adjust_delta < 0 && g.DragCurrentAccum > 0) || (adjust_delta > 0 && g.DragCurrentAccum < 0));
1988  if (is_just_activated || is_already_past_limits_and_pushing_outward || is_drag_direction_change_with_power)
1989  {
1990  g.DragCurrentAccum = 0.0f;
1991  g.DragCurrentAccumDirty = false;
1992  }
1993  else if (adjust_delta != 0.0f)
1994  {
1995  g.DragCurrentAccum += adjust_delta;
1996  g.DragCurrentAccumDirty = true;
1997  }
1998 
1999  if (!g.DragCurrentAccumDirty)
2000  return false;
2001 
2002  TYPE v_cur = *v;
2003  FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f;
2004 
2005  if (is_power)
2006  {
2007  // 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
2008  FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power);
2009  FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min));
2010  v_cur = v_min + (SIGNEDTYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min);
2011  v_old_ref_for_accum_remainder = v_old_norm_curved;
2012  }
2013  else
2014  {
2015  v_cur += (SIGNEDTYPE)g.DragCurrentAccum;
2016  }
2017 
2018  // Round to user desired precision based on format string
2019  v_cur = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_cur);
2020 
2021  // Preserve remainder after rounding has been applied. This also allow slow tweaking of values.
2022  g.DragCurrentAccumDirty = false;
2023  if (is_power)
2024  {
2025  FLOATTYPE v_cur_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power);
2026  g.DragCurrentAccum -= (float)(v_cur_norm_curved - v_old_ref_for_accum_remainder);
2027  }
2028  else
2029  {
2030  g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*v);
2031  }
2032 
2033  // Lose zero sign for float/double
2034  if (v_cur == (TYPE)-0)
2035  v_cur = (TYPE)0;
2036 
2037  // Clamp values (+ handle overflow/wrap-around for integer types)
2038  if (*v != v_cur && is_clamped)
2039  {
2040  if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_decimal))
2041  v_cur = v_min;
2042  if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_decimal))
2043  v_cur = v_max;
2044  }
2045 
2046  // Apply result
2047  if (*v == v_cur)
2048  return false;
2049  *v = v_cur;
2050  return true;
2051 }
2052 
2053 bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, float power, ImGuiDragFlags flags)
2054 {
2055  ImGuiContext& g = *GImGui;
2056  if (g.ActiveId == id)
2057  {
2058  if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
2059  ClearActiveID();
2060  else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
2061  ClearActiveID();
2062  }
2063  if (g.ActiveId != id)
2064  return false;
2065 
2066  switch (data_type)
2067  {
2068  case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = DragBehaviorT<ImS32, ImS32, float>(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS8*) p_min : IM_S8_MIN, p_max ? *(const ImS8*)p_max : IM_S8_MAX, format, power, flags); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
2069  case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = DragBehaviorT<ImU32, ImS32, float>(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU8*) p_min : IM_U8_MIN, p_max ? *(const ImU8*)p_max : IM_U8_MAX, format, power, flags); if (r) *(ImU8*)p_v = (ImU8)v32; return r; }
2070  case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = DragBehaviorT<ImS32, ImS32, float>(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS16*)p_min : IM_S16_MIN, p_max ? *(const ImS16*)p_max : IM_S16_MAX, format, power, flags); if (r) *(ImS16*)p_v = (ImS16)v32; return r; }
2071  case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = DragBehaviorT<ImU32, ImS32, float>(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU16*)p_min : IM_U16_MIN, p_max ? *(const ImU16*)p_max : IM_U16_MAX, format, power, flags); if (r) *(ImU16*)p_v = (ImU16)v32; return r; }
2072  case ImGuiDataType_S32: return DragBehaviorT<ImS32, ImS32, float >(data_type, (ImS32*)p_v, v_speed, p_min ? *(const ImS32* )p_min : IM_S32_MIN, p_max ? *(const ImS32* )p_max : IM_S32_MAX, format, power, flags);
2073  case ImGuiDataType_U32: return DragBehaviorT<ImU32, ImS32, float >(data_type, (ImU32*)p_v, v_speed, p_min ? *(const ImU32* )p_min : IM_U32_MIN, p_max ? *(const ImU32* )p_max : IM_U32_MAX, format, power, flags);
2074  case ImGuiDataType_S64: return DragBehaviorT<ImS64, ImS64, double>(data_type, (ImS64*)p_v, v_speed, p_min ? *(const ImS64* )p_min : IM_S64_MIN, p_max ? *(const ImS64* )p_max : IM_S64_MAX, format, power, flags);
2075  case ImGuiDataType_U64: return DragBehaviorT<ImU64, ImS64, double>(data_type, (ImU64*)p_v, v_speed, p_min ? *(const ImU64* )p_min : IM_U64_MIN, p_max ? *(const ImU64* )p_max : IM_U64_MAX, format, power, flags);
2076  case ImGuiDataType_Float: return DragBehaviorT<float, float, float >(data_type, (float*)p_v, v_speed, p_min ? *(const float* )p_min : -FLT_MAX, p_max ? *(const float* )p_max : FLT_MAX, format, power, flags);
2077  case ImGuiDataType_Double: return DragBehaviorT<double,double,double>(data_type, (double*)p_v, v_speed, p_min ? *(const double*)p_min : -DBL_MAX, p_max ? *(const double*)p_max : DBL_MAX, format, power, flags);
2078  case ImGuiDataType_COUNT: break;
2079  }
2080  IM_ASSERT(0);
2081  return false;
2082 }
2083 
2084 // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional.
2085 // Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
2086 bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power)
2087 {
2088  ImGuiWindow* window = GetCurrentWindow();
2089  if (window->SkipItems)
2090  return false;
2091 
2092  if (power != 1.0f)
2093  IM_ASSERT(p_min != NULL && p_max != NULL); // When using a power curve the drag needs to have known bounds
2094 
2095  ImGuiContext& g = *GImGui;
2096  const ImGuiStyle& style = g.Style;
2097  const ImGuiID id = window->GetID(label);
2098  const float w = CalcItemWidth();
2099  const ImVec2 label_size = CalcTextSize(label, NULL, true);
2100  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
2101  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));
2102 
2103  ItemSize(total_bb, style.FramePadding.y);
2104  if (!ItemAdd(total_bb, id, &frame_bb))
2105  return false;
2106 
2107  // Default format string when passing NULL
2108  if (format == NULL)
2109  format = DataTypeGetInfo(data_type)->PrintFmt;
2110  else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) // (FIXME-LEGACY: Patch old "%.0f" format string to use "%d", read function more details.)
2112 
2113  // Tabbing or CTRL-clicking on Drag turns it into an input box
2114  const bool hovered = ItemHoverable(frame_bb, id);
2115  bool temp_input_is_active = TempInputIsActive(id);
2116  bool temp_input_start = false;
2117  if (!temp_input_is_active)
2118  {
2119  const bool focus_requested = FocusableItemRegister(window, id);
2120  const bool clicked = (hovered && g.IO.MouseClicked[0]);
2121  const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]);
2122  if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavInputId == id)
2123  {
2124  SetActiveID(id, window);
2125  SetFocusID(id, window);
2126  FocusWindow(window);
2127  g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
2128  if (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id)
2129  {
2130  temp_input_start = true;
2131  FocusableItemUnregister(window);
2132  }
2133  }
2134  }
2135  if (temp_input_is_active || temp_input_start)
2136  return TempInputScalar(frame_bb, id, label, data_type, p_data, format);
2137 
2138  // Draw frame
2139  const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
2140  RenderNavHighlight(frame_bb, id);
2141  RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
2142 
2143  // Drag behavior
2144  const bool value_changed = DragBehavior(id, data_type, p_data, v_speed, p_min, p_max, format, power, ImGuiDragFlags_None);
2145  if (value_changed)
2146  MarkItemEdited(id);
2147 
2148  // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
2149  char value_buf[64];
2150  const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
2151  RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
2152 
2153  if (label_size.x > 0.0f)
2154  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
2155 
2157  return value_changed;
2158 }
2159 
2160 bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power)
2161 {
2162  ImGuiWindow* window = GetCurrentWindow();
2163  if (window->SkipItems)
2164  return false;
2165 
2166  ImGuiContext& g = *GImGui;
2167  bool value_changed = false;
2168  BeginGroup();
2169  PushID(label);
2170  PushMultiItemsWidths(components, CalcItemWidth());
2171  size_t type_size = GDataTypeInfo[data_type].Size;
2172  for (int i = 0; i < components; i++)
2173  {
2174  PushID(i);
2175  if (i > 0)
2176  SameLine(0, g.Style.ItemInnerSpacing.x);
2177  value_changed |= DragScalar("", data_type, p_data, v_speed, p_min, p_max, format, power);
2178  PopID();
2179  PopItemWidth();
2180  p_data = (void*)((char*)p_data + type_size);
2181  }
2182  PopID();
2183 
2184  const char* label_end = FindRenderedTextEnd(label);
2185  if (label != label_end)
2186  {
2187  SameLine(0, g.Style.ItemInnerSpacing.x);
2188  TextEx(label, label_end);
2189  }
2190 
2191  EndGroup();
2192  return value_changed;
2193 }
2194 
2195 bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power)
2196 {
2197  return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, power);
2198 }
2199 
2200 bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power)
2201 {
2202  return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, power);
2203 }
2204 
2205 bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power)
2206 {
2207  return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, power);
2208 }
2209 
2210 bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power)
2211 {
2212  return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, power);
2213 }
2214 
2215 bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, float power)
2216 {
2217  ImGuiWindow* window = GetCurrentWindow();
2218  if (window->SkipItems)
2219  return false;
2220 
2221  ImGuiContext& g = *GImGui;
2222  PushID(label);
2223  BeginGroup();
2225 
2226  bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format, power);
2227  PopItemWidth();
2228  SameLine(0, g.Style.ItemInnerSpacing.x);
2229  value_changed |= DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, format_max ? format_max : format, power);
2230  PopItemWidth();
2231  SameLine(0, g.Style.ItemInnerSpacing.x);
2232 
2234  EndGroup();
2235  PopID();
2236  return value_changed;
2237 }
2238 
2239 // NB: v_speed is float to allow adjusting the drag speed with more precision
2240 bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format)
2241 {
2242  return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format);
2243 }
2244 
2245 bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format)
2246 {
2247  return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format);
2248 }
2249 
2250 bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format)
2251 {
2252  return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format);
2253 }
2254 
2255 bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format)
2256 {
2257  return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format);
2258 }
2259 
2260 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)
2261 {
2262  ImGuiWindow* window = GetCurrentWindow();
2263  if (window->SkipItems)
2264  return false;
2265 
2266  ImGuiContext& g = *GImGui;
2267  PushID(label);
2268  BeginGroup();
2270 
2271  bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format);
2272  PopItemWidth();
2273  SameLine(0, g.Style.ItemInnerSpacing.x);
2274  value_changed |= DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, format_max ? format_max : format);
2275  PopItemWidth();
2276  SameLine(0, g.Style.ItemInnerSpacing.x);
2277 
2279  EndGroup();
2280  PopID();
2281 
2282  return value_changed;
2283 }
2284 
2285 //-------------------------------------------------------------------------
2286 // [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc.
2287 //-------------------------------------------------------------------------
2288 // - SliderBehaviorT<>() [Internal]
2289 // - SliderBehavior() [Internal]
2290 // - SliderScalar()
2291 // - SliderScalarN()
2292 // - SliderFloat()
2293 // - SliderFloat2()
2294 // - SliderFloat3()
2295 // - SliderFloat4()
2296 // - SliderAngle()
2297 // - SliderInt()
2298 // - SliderInt2()
2299 // - SliderInt3()
2300 // - SliderInt4()
2301 // - VSliderScalar()
2302 // - VSliderFloat()
2303 // - VSliderInt()
2304 //-------------------------------------------------------------------------
2305 
2306 template<typename TYPE, typename FLOATTYPE>
2307 float ImGui::SliderCalcRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, float power, float linear_zero_pos)
2308 {
2309  if (v_min == v_max)
2310  return 0.0f;
2311 
2312  const bool is_power = (power != 1.0f) && (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double);
2313  const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min);
2314  if (is_power)
2315  {
2316  if (v_clamped < 0.0f)
2317  {
2318  const float f = 1.0f - (float)((v_clamped - v_min) / (ImMin((TYPE)0, v_max) - v_min));
2319  return (1.0f - ImPow(f, 1.0f/power)) * linear_zero_pos;
2320  }
2321  else
2322  {
2323  const float f = (float)((v_clamped - ImMax((TYPE)0, v_min)) / (v_max - ImMax((TYPE)0, v_min)));
2324  return linear_zero_pos + ImPow(f, 1.0f/power) * (1.0f - linear_zero_pos);
2325  }
2326  }
2327 
2328  // Linear slider
2329  return (float)((FLOATTYPE)(v_clamped - v_min) / (FLOATTYPE)(v_max - v_min));
2330 }
2331 
2332 // FIXME: Move some of the code into SliderBehavior(). Current responsability is larger than what the equivalent DragBehaviorT<> does, we also do some rendering, etc.
2333 template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
2334 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)
2335 {
2336  ImGuiContext& g = *GImGui;
2337  const ImGuiStyle& style = g.Style;
2338 
2340  const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
2341  const bool is_power = (power != 1.0f) && is_decimal;
2342 
2343  const float grab_padding = 2.0f;
2344  const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f;
2345  float grab_sz = style.GrabMinSize;
2346  SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
2347  if (!is_decimal && v_range >= 0) // v_range < 0 may happen on integer overflows
2348  grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit
2349  grab_sz = ImMin(grab_sz, slider_sz);
2350  const float slider_usable_sz = slider_sz - grab_sz;
2351  const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz * 0.5f;
2352  const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz * 0.5f;
2353 
2354  // For power curve sliders that cross over sign boundary we want the curve to be symmetric around 0.0f
2355  float linear_zero_pos; // 0.0->1.0f
2356  if (is_power && v_min * v_max < 0.0f)
2357  {
2358  // Different sign
2359  const FLOATTYPE linear_dist_min_to_0 = ImPow(v_min >= 0 ? (FLOATTYPE)v_min : -(FLOATTYPE)v_min, (FLOATTYPE)1.0f / power);
2360  const FLOATTYPE linear_dist_max_to_0 = ImPow(v_max >= 0 ? (FLOATTYPE)v_max : -(FLOATTYPE)v_max, (FLOATTYPE)1.0f / power);
2361  linear_zero_pos = (float)(linear_dist_min_to_0 / (linear_dist_min_to_0 + linear_dist_max_to_0));
2362  }
2363  else
2364  {
2365  // Same sign
2366  linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f;
2367  }
2368 
2369  // Process interacting with the slider
2370  bool value_changed = false;
2371  if (g.ActiveId == id)
2372  {
2373  bool set_new_value = false;
2374  float clicked_t = 0.0f;
2375  if (g.ActiveIdSource == ImGuiInputSource_Mouse)
2376  {
2377  if (!g.IO.MouseDown[0])
2378  {
2379  ClearActiveID();
2380  }
2381  else
2382  {
2383  const float mouse_abs_pos = g.IO.MousePos[axis];
2384  clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f;
2385  if (axis == ImGuiAxis_Y)
2386  clicked_t = 1.0f - clicked_t;
2387  set_new_value = true;
2388  }
2389  }
2390  else if (g.ActiveIdSource == ImGuiInputSource_Nav)
2391  {
2393  float delta = (axis == ImGuiAxis_X) ? delta2.x : -delta2.y;
2394  if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
2395  {
2396  ClearActiveID();
2397  }
2398  else if (delta != 0.0f)
2399  {
2400  clicked_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
2401  const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
2402  if ((decimal_precision > 0) || is_power)
2403  {
2404  delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds
2406  delta /= 10.0f;
2407  }
2408  else
2409  {
2410  if ((v_range >= -100.0f && v_range <= 100.0f) || IsNavInputDown(ImGuiNavInput_TweakSlow))
2411  delta = ((delta < 0.0f) ? -1.0f : +1.0f) / (float)v_range; // Gamepad/keyboard tweak speeds in integer steps
2412  else
2413  delta /= 100.0f;
2414  }
2416  delta *= 10.0f;
2417  set_new_value = true;
2418  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
2419  set_new_value = false;
2420  else
2421  clicked_t = ImSaturate(clicked_t + delta);
2422  }
2423  }
2424 
2425  if (set_new_value)
2426  {
2427  TYPE v_new;
2428  if (is_power)
2429  {
2430  // Account for power curve scale on both sides of the zero
2431  if (clicked_t < linear_zero_pos)
2432  {
2433  // Negative: rescale to the negative range before powering
2434  float a = 1.0f - (clicked_t / linear_zero_pos);
2435  a = ImPow(a, power);
2436  v_new = ImLerp(ImMin(v_max, (TYPE)0), v_min, a);
2437  }
2438  else
2439  {
2440  // Positive: rescale to the positive range before powering
2441  float a;
2442  if (ImFabs(linear_zero_pos - 1.0f) > 1.e-6f)
2443  a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos);
2444  else
2445  a = clicked_t;
2446  a = ImPow(a, power);
2447  v_new = ImLerp(ImMax(v_min, (TYPE)0), v_max, a);
2448  }
2449  }
2450  else
2451  {
2452  // Linear slider
2453  if (is_decimal)
2454  {
2455  v_new = ImLerp(v_min, v_max, clicked_t);
2456  }
2457  else
2458  {
2459  // For integer values we want the clicking position to match the grab box so we round above
2460  // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property..
2461  FLOATTYPE v_new_off_f = (v_max - v_min) * clicked_t;
2462  TYPE v_new_off_floor = (TYPE)(v_new_off_f);
2463  TYPE v_new_off_round = (TYPE)(v_new_off_f + (FLOATTYPE)0.5);
2464  if (v_new_off_floor < v_new_off_round)
2465  v_new = v_min + v_new_off_round;
2466  else
2467  v_new = v_min + v_new_off_floor;
2468  }
2469  }
2470 
2471  // Round to user desired precision based on format string
2472  v_new = RoundScalarWithFormatT<TYPE,SIGNEDTYPE>(format, data_type, v_new);
2473 
2474  // Apply result
2475  if (*v != v_new)
2476  {
2477  *v = v_new;
2478  value_changed = true;
2479  }
2480  }
2481  }
2482 
2483  if (slider_sz < 1.0f)
2484  {
2485  *out_grab_bb = ImRect(bb.Min, bb.Min);
2486  }
2487  else
2488  {
2489  // Output grab position so it can be displayed by the caller
2490  float grab_t = SliderCalcRatioFromValueT<TYPE, FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
2491  if (axis == ImGuiAxis_Y)
2492  grab_t = 1.0f - grab_t;
2493  const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
2494  if (axis == ImGuiAxis_X)
2495  *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);
2496  else
2497  *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz * 0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz * 0.5f);
2498  }
2499 
2500  return value_changed;
2501 }
2502 
2503 // For 32-bit and larger types, slider bounds are limited to half the natural type range.
2504 // 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.
2505 // It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders.
2506 bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb)
2507 {
2508  switch (data_type)
2509  {
2510  case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, power, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
2511  case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = SliderBehaviorT<ImU32, ImS32, float>(bb, id, ImGuiDataType_U32, &v32, *(const ImU8*)p_min, *(const ImU8*)p_max, format, power, flags, out_grab_bb); if (r) *(ImU8*)p_v = (ImU8)v32; return r; }
2512  case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)p_min, *(const ImS16*)p_max, format, power, flags, out_grab_bb); if (r) *(ImS16*)p_v = (ImS16)v32; return r; }
2513  case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = SliderBehaviorT<ImU32, ImS32, float>(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)p_min, *(const ImU16*)p_max, format, power, flags, out_grab_bb); if (r) *(ImU16*)p_v = (ImU16)v32; return r; }
2514  case ImGuiDataType_S32:
2515  IM_ASSERT(*(const ImS32*)p_min >= IM_S32_MIN/2 && *(const ImS32*)p_max <= IM_S32_MAX/2);
2516  return SliderBehaviorT<ImS32, ImS32, float >(bb, id, data_type, (ImS32*)p_v, *(const ImS32*)p_min, *(const ImS32*)p_max, format, power, flags, out_grab_bb);
2517  case ImGuiDataType_U32:
2518  IM_ASSERT(*(const ImU32*)p_max <= IM_U32_MAX/2);
2519  return SliderBehaviorT<ImU32, ImS32, float >(bb, id, data_type, (ImU32*)p_v, *(const ImU32*)p_min, *(const ImU32*)p_max, format, power, flags, out_grab_bb);
2520  case ImGuiDataType_S64:
2521  IM_ASSERT(*(const ImS64*)p_min >= IM_S64_MIN/2 && *(const ImS64*)p_max <= IM_S64_MAX/2);
2522  return SliderBehaviorT<ImS64, ImS64, double>(bb, id, data_type, (ImS64*)p_v, *(const ImS64*)p_min, *(const ImS64*)p_max, format, power, flags, out_grab_bb);
2523  case ImGuiDataType_U64:
2524  IM_ASSERT(*(const ImU64*)p_max <= IM_U64_MAX/2);
2525  return SliderBehaviorT<ImU64, ImS64, double>(bb, id, data_type, (ImU64*)p_v, *(const ImU64*)p_min, *(const ImU64*)p_max, format, power, flags, out_grab_bb);
2526  case ImGuiDataType_Float:
2527  IM_ASSERT(*(const float*)p_min >= -FLT_MAX/2.0f && *(const float*)p_max <= FLT_MAX/2.0f);
2528  return SliderBehaviorT<float, float, float >(bb, id, data_type, (float*)p_v, *(const float*)p_min, *(const float*)p_max, format, power, flags, out_grab_bb);
2529  case ImGuiDataType_Double:
2530  IM_ASSERT(*(const double*)p_min >= -DBL_MAX/2.0f && *(const double*)p_max <= DBL_MAX/2.0f);
2531  return SliderBehaviorT<double,double,double>(bb, id, data_type, (double*)p_v, *(const double*)p_min, *(const double*)p_max, format, power, flags, out_grab_bb);
2532  case ImGuiDataType_COUNT: break;
2533  }
2534  IM_ASSERT(0);
2535  return false;
2536 }
2537 
2538 // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a slider, they are all required.
2539 // Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
2540 bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power)
2541 {
2542  ImGuiWindow* window = GetCurrentWindow();
2543  if (window->SkipItems)
2544  return false;
2545 
2546  ImGuiContext& g = *GImGui;
2547  const ImGuiStyle& style = g.Style;
2548  const ImGuiID id = window->GetID(label);
2549  const float w = CalcItemWidth();
2550 
2551  const ImVec2 label_size = CalcTextSize(label, NULL, true);
2552  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
2553  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));
2554 
2555  ItemSize(total_bb, style.FramePadding.y);
2556  if (!ItemAdd(total_bb, id, &frame_bb))
2557  return false;
2558 
2559  // Default format string when passing NULL
2560  if (format == NULL)
2561  format = DataTypeGetInfo(data_type)->PrintFmt;
2562  else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) // (FIXME-LEGACY: Patch old "%.0f" format string to use "%d", read function more details.)
2564 
2565  // Tabbing or CTRL-clicking on Slider turns it into an input box
2566  const bool hovered = ItemHoverable(frame_bb, id);
2567  bool temp_input_is_active = TempInputIsActive(id);
2568  bool temp_input_start = false;
2569  if (!temp_input_is_active)
2570  {
2571  const bool focus_requested = FocusableItemRegister(window, id);
2572  const bool clicked = (hovered && g.IO.MouseClicked[0]);
2573  if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id)
2574  {
2575  SetActiveID(id, window);
2576  SetFocusID(id, window);
2577  FocusWindow(window);
2578  g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
2579  if (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id)
2580  {
2581  temp_input_start = true;
2582  FocusableItemUnregister(window);
2583  }
2584  }
2585  }
2586  if (temp_input_is_active || temp_input_start)
2587  return TempInputScalar(frame_bb, id, label, data_type, p_data, format);
2588 
2589  // Draw frame
2590  const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
2591  RenderNavHighlight(frame_bb, id);
2592  RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
2593 
2594  // Slider behavior
2595  ImRect grab_bb;
2596  const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, power, ImGuiSliderFlags_None, &grab_bb);
2597  if (value_changed)
2598  MarkItemEdited(id);
2599 
2600  // Render grab
2601  if (grab_bb.Max.x > grab_bb.Min.x)
2602  window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
2603 
2604  // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
2605  char value_buf[64];
2606  const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
2607  RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f));
2608 
2609  if (label_size.x > 0.0f)
2610  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
2611 
2613  return value_changed;
2614 }
2615 
2616 // Add multiple sliders on 1 line for compact edition of multiple components
2617 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)
2618 {
2619  ImGuiWindow* window = GetCurrentWindow();
2620  if (window->SkipItems)
2621  return false;
2622 
2623  ImGuiContext& g = *GImGui;
2624  bool value_changed = false;
2625  BeginGroup();
2626  PushID(label);
2627  PushMultiItemsWidths(components, CalcItemWidth());
2628  size_t type_size = GDataTypeInfo[data_type].Size;
2629  for (int i = 0; i < components; i++)
2630  {
2631  PushID(i);
2632  if (i > 0)
2633  SameLine(0, g.Style.ItemInnerSpacing.x);
2634  value_changed |= SliderScalar("", data_type, v, v_min, v_max, format, power);
2635  PopID();
2636  PopItemWidth();
2637  v = (void*)((char*)v + type_size);
2638  }
2639  PopID();
2640 
2641  const char* label_end = FindRenderedTextEnd(label);
2642  if (label != label_end)
2643  {
2644  SameLine(0, g.Style.ItemInnerSpacing.x);
2645  TextEx(label, label_end);
2646  }
2647 
2648  EndGroup();
2649  return value_changed;
2650 }
2651 
2652 bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power)
2653 {
2654  return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power);
2655 }
2656 
2657 bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power)
2658 {
2659  return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power);
2660 }
2661 
2662 bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power)
2663 {
2664  return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power);
2665 }
2666 
2667 bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power)
2668 {
2669  return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power);
2670 }
2671 
2672 bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format)
2673 {
2674  if (format == NULL)
2675  format = "%.0f deg";
2676  float v_deg = (*v_rad) * 360.0f / (2*IM_PI);
2677  bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, 1.0f);
2678  *v_rad = v_deg * (2*IM_PI) / 360.0f;
2679  return value_changed;
2680 }
2681 
2682 bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format)
2683 {
2684  return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format);
2685 }
2686 
2687 bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format)
2688 {
2689  return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format);
2690 }
2691 
2692 bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format)
2693 {
2694  return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format);
2695 }
2696 
2697 bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format)
2698 {
2699  return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format);
2700 }
2701 
2702 bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power)
2703 {
2704  ImGuiWindow* window = GetCurrentWindow();
2705  if (window->SkipItems)
2706  return false;
2707 
2708  ImGuiContext& g = *GImGui;
2709  const ImGuiStyle& style = g.Style;
2710  const ImGuiID id = window->GetID(label);
2711 
2712  const ImVec2 label_size = CalcTextSize(label, NULL, true);
2713  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
2714  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));
2715 
2716  ItemSize(bb, style.FramePadding.y);
2717  if (!ItemAdd(frame_bb, id))
2718  return false;
2719 
2720  // Default format string when passing NULL
2721  if (format == NULL)
2722  format = DataTypeGetInfo(data_type)->PrintFmt;
2723  else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) // (FIXME-LEGACY: Patch old "%.0f" format string to use "%d", read function more details.)
2725 
2726  const bool hovered = ItemHoverable(frame_bb, id);
2727  if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id)
2728  {
2729  SetActiveID(id, window);
2730  SetFocusID(id, window);
2731  FocusWindow(window);
2732  g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
2733  }
2734 
2735  // Draw frame
2736  const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
2737  RenderNavHighlight(frame_bb, id);
2738  RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
2739 
2740  // Slider behavior
2741  ImRect grab_bb;
2742  const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, power, ImGuiSliderFlags_Vertical, &grab_bb);
2743  if (value_changed)
2744  MarkItemEdited(id);
2745 
2746  // Render grab
2747  if (grab_bb.Max.y > grab_bb.Min.y)
2748  window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
2749 
2750  // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
2751  // For the vertical slider we allow centered text to overlap the frame padding
2752  char value_buf[64];
2753  const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
2754  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));
2755  if (label_size.x > 0.0f)
2756  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
2757 
2758  return value_changed;
2759 }
2760 
2761 bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, float power)
2762 {
2763  return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, power);
2764 }
2765 
2766 bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format)
2767 {
2768  return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format);
2769 }
2770 
2771 //-------------------------------------------------------------------------
2772 // [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc.
2773 //-------------------------------------------------------------------------
2774 // - ImParseFormatFindStart() [Internal]
2775 // - ImParseFormatFindEnd() [Internal]
2776 // - ImParseFormatTrimDecorations() [Internal]
2777 // - ImParseFormatPrecision() [Internal]
2778 // - TempInputTextScalar() [Internal]
2779 // - InputScalar()
2780 // - InputScalarN()
2781 // - InputFloat()
2782 // - InputFloat2()
2783 // - InputFloat3()
2784 // - InputFloat4()
2785 // - InputInt()
2786 // - InputInt2()
2787 // - InputInt3()
2788 // - InputInt4()
2789 // - InputDouble()
2790 //-------------------------------------------------------------------------
2791 
2792 // We don't use strchr() because our strings are usually very short and often start with '%'
2793 const char* ImParseFormatFindStart(const char* fmt)
2794 {
2795  while (char c = fmt[0])
2796  {
2797  if (c == '%' && fmt[1] != '%')
2798  return fmt;
2799  else if (c == '%')
2800  fmt++;
2801  fmt++;
2802  }
2803  return fmt;
2804 }
2805 
2806 const char* ImParseFormatFindEnd(const char* fmt)
2807 {
2808  // Printf/scanf types modifiers: I/L/h/j/l/t/w/z. Other uppercase letters qualify as types aka end of the format.
2809  if (fmt[0] != '%')
2810  return fmt;
2811  const unsigned int ignored_uppercase_mask = (1 << ('I'-'A')) | (1 << ('L'-'A'));
2812  const unsigned int ignored_lowercase_mask = (1 << ('h'-'a')) | (1 << ('j'-'a')) | (1 << ('l'-'a')) | (1 << ('t'-'a')) | (1 << ('w'-'a')) | (1 << ('z'-'a'));
2813  for (char c; (c = *fmt) != 0; fmt++)
2814  {
2815  if (c >= 'A' && c <= 'Z' && ((1 << (c - 'A')) & ignored_uppercase_mask) == 0)
2816  return fmt + 1;
2817  if (c >= 'a' && c <= 'z' && ((1 << (c - 'a')) & ignored_lowercase_mask) == 0)
2818  return fmt + 1;
2819  }
2820  return fmt;
2821 }
2822 
2823 // Extract the format out of a format string with leading or trailing decorations
2824 // fmt = "blah blah" -> return fmt
2825 // fmt = "%.3f" -> return fmt
2826 // fmt = "hello %.3f" -> return fmt + 6
2827 // fmt = "%.3f hello" -> return buf written with "%.3f"
2828 const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, size_t buf_size)
2829 {
2830  const char* fmt_start = ImParseFormatFindStart(fmt);
2831  if (fmt_start[0] != '%')
2832  return fmt;
2833  const char* fmt_end = ImParseFormatFindEnd(fmt_start);
2834  if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data.
2835  return fmt_start;
2836  ImStrncpy(buf, fmt_start, ImMin((size_t)(fmt_end - fmt_start) + 1, buf_size));
2837  return buf;
2838 }
2839 
2840 // Parse display precision back from the display format string
2841 // 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.
2842 int ImParseFormatPrecision(const char* fmt, int default_precision)
2843 {
2845  if (fmt[0] != '%')
2846  return default_precision;
2847  fmt++;
2848  while (*fmt >= '0' && *fmt <= '9')
2849  fmt++;
2850  int precision = INT_MAX;
2851  if (*fmt == '.')
2852  {
2853  fmt = ImAtoi<int>(fmt + 1, &precision);
2855  precision = default_precision;
2856  }
2857  if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation
2858  precision = -1;
2859  if ((*fmt == 'g' || *fmt == 'G') && precision == INT_MAX)
2860  precision = -1;
2861  return (precision == INT_MAX) ? default_precision : precision;
2862 }
2863 
2864 // Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets)
2865 // FIXME: Facilitate using this in variety of other situations.
2866 bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags)
2867 {
2868  // On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id.
2869  // We clear ActiveID on the first frame to allow the InputText() taking it back.
2870  ImGuiContext& g = *GImGui;
2871  const bool init = (g.TempInputId != id);
2872  if (init)
2873  ClearActiveID();
2874 
2875  g.CurrentWindow->DC.CursorPos = bb.Min;
2876  bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags);
2877  if (init)
2878  {
2879  // First frame we started displaying the InputText widget, we expect it to take the active id.
2880  IM_ASSERT(g.ActiveId == id);
2881  g.TempInputId = g.ActiveId;
2882  }
2883  return value_changed;
2884 }
2885 
2886 bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format)
2887 {
2888  ImGuiContext& g = *GImGui;
2889 
2890  char fmt_buf[32];
2891  char data_buf[32];
2893  DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
2894  ImStrTrimBlanks(data_buf);
2895 
2898  bool value_changed = TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags);
2899  if (value_changed)
2900  {
2901  value_changed = DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL);
2902  if (value_changed)
2903  MarkItemEdited(id);
2904  }
2905  return value_changed;
2906 }
2907 
2908 // Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional.
2909 // Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
2910 bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags)
2911 {
2912  ImGuiWindow* window = GetCurrentWindow();
2913  if (window->SkipItems)
2914  return false;
2915 
2916  ImGuiContext& g = *GImGui;
2917  ImGuiStyle& style = g.Style;
2918 
2919  if (format == NULL)
2920  format = DataTypeGetInfo(data_type)->PrintFmt;
2921 
2922  char buf[64];
2923  DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
2924 
2925  bool value_changed = false;
2929  flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselve by comparing the actual data rather than the string.
2930 
2931  if (p_step != NULL)
2932  {
2933  const float button_size = GetFrameHeight();
2934 
2935  BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
2936  PushID(label);
2937  SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
2938  if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
2939  value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
2940 
2941  // Step buttons
2942  const ImVec2 backup_frame_padding = style.FramePadding;
2943  style.FramePadding.x = style.FramePadding.y;
2946  button_flags |= ImGuiButtonFlags_Disabled;
2947  SameLine(0, style.ItemInnerSpacing.x);
2948  if (ButtonEx("-", ImVec2(button_size, button_size), button_flags))
2949  {
2950  DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
2951  value_changed = true;
2952  }
2953  SameLine(0, style.ItemInnerSpacing.x);
2954  if (ButtonEx("+", ImVec2(button_size, button_size), button_flags))
2955  {
2956  DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
2957  value_changed = true;
2958  }
2959 
2960  const char* label_end = FindRenderedTextEnd(label);
2961  if (label != label_end)
2962  {
2963  SameLine(0, style.ItemInnerSpacing.x);
2964  TextEx(label, label_end);
2965  }
2966  style.FramePadding = backup_frame_padding;
2967 
2968  PopID();
2969  EndGroup();
2970  }
2971  else
2972  {
2974  value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
2975  }
2976  if (value_changed)
2977  MarkItemEdited(window->DC.LastItemId);
2978 
2979  return value_changed;
2980 }
2981 
2982 bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags)
2983 {
2984  ImGuiWindow* window = GetCurrentWindow();
2985  if (window->SkipItems)
2986  return false;
2987 
2988  ImGuiContext& g = *GImGui;
2989  bool value_changed = false;
2990  BeginGroup();
2991  PushID(label);
2992  PushMultiItemsWidths(components, CalcItemWidth());
2993  size_t type_size = GDataTypeInfo[data_type].Size;
2994  for (int i = 0; i < components; i++)
2995  {
2996  PushID(i);
2997  if (i > 0)
2998  SameLine(0, g.Style.ItemInnerSpacing.x);
2999  value_changed |= InputScalar("", data_type, p_data, p_step, p_step_fast, format, flags);
3000  PopID();
3001  PopItemWidth();
3002  p_data = (void*)((char*)p_data + type_size);
3003  }
3004  PopID();
3005 
3006  const char* label_end = FindRenderedTextEnd(label);
3007  if (label != label_end)
3008  {
3009  SameLine(0.0f, g.Style.ItemInnerSpacing.x);
3010  TextEx(label, label_end);
3011  }
3012 
3013  EndGroup();
3014  return value_changed;
3015 }
3016 
3017 bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags)
3018 {
3020  return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, flags);
3021 }
3022 
3023 bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags)
3024 {
3026 }
3027 
3028 bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags flags)
3029 {
3031 }
3032 
3033 bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags flags)
3034 {
3036 }
3037 
3038 // Prefer using "const char* format" directly, which is more flexible and consistent with other API.
3039 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
3040 bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags flags)
3041 {
3042  char format[16] = "%f";
3043  if (decimal_precision >= 0)
3044  ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
3045  return InputFloat(label, v, step, step_fast, format, flags);
3046 }
3047 
3048 bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags flags)
3049 {
3050  char format[16] = "%f";
3051  if (decimal_precision >= 0)
3052  ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
3054 }
3055 
3056 bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags flags)
3057 {
3058  char format[16] = "%f";
3059  if (decimal_precision >= 0)
3060  ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
3062 }
3063 
3064 bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags flags)
3065 {
3066  char format[16] = "%f";
3067  if (decimal_precision >= 0)
3068  ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
3070 }
3071 #endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
3072 
3073 bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags flags)
3074 {
3075  // 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.
3076  const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d";
3077  return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, flags);
3078 }
3079 
3081 {
3082  return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", flags);
3083 }
3084 
3086 {
3087  return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", flags);
3088 }
3089 
3091 {
3092  return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags);
3093 }
3094 
3095 bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags)
3096 {
3098  return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), format, flags);
3099 }
3100 
3101 //-------------------------------------------------------------------------
3102 // [SECTION] Widgets: InputText, InputTextMultiline, InputTextWithHint
3103 //-------------------------------------------------------------------------
3104 // - InputText()
3105 // - InputTextWithHint()
3106 // - InputTextMultiline()
3107 // - InputTextEx() [Internal]
3108 //-------------------------------------------------------------------------
3109 
3110 bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
3111 {
3112  IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
3113  return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data);
3114 }
3115 
3116 bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
3117 {
3118  return InputTextEx(label, NULL, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);
3119 }
3120 
3121 bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
3122 {
3123  IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
3124  return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
3125 }
3126 
3127 static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
3128 {
3129  int line_count = 0;
3130  const char* s = text_begin;
3131  while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding
3132  if (c == '\n')
3133  line_count++;
3134  s--;
3135  if (s[0] != '\n' && s[0] != '\r')
3136  line_count++;
3137  *out_text_end = s;
3138  return line_count;
3139 }
3140 
3141 static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line)
3142 {
3143  ImGuiContext& g = *GImGui;
3144  ImFont* font = g.Font;
3145  const float line_height = g.FontSize;
3146  const float scale = line_height / font->FontSize;
3147 
3148  ImVec2 text_size = ImVec2(0,0);
3149  float line_width = 0.0f;
3150 
3151  const ImWchar* s = text_begin;
3152  while (s < text_end)
3153  {
3154  unsigned int c = (unsigned int)(*s++);
3155  if (c == '\n')
3156  {
3157  text_size.x = ImMax(text_size.x, line_width);
3158  text_size.y += line_height;
3159  line_width = 0.0f;
3160  if (stop_on_new_line)
3161  break;
3162  continue;
3163  }
3164  if (c == '\r')
3165  continue;
3166 
3167  const float char_width = font->GetCharAdvance((ImWchar)c) * scale;
3168  line_width += char_width;
3169  }
3170 
3171  if (text_size.x < line_width)
3172  text_size.x = line_width;
3173 
3174  if (out_offset)
3175  *out_offset = ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n
3176 
3177  if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n
3178  text_size.y += line_height;
3179 
3180  if (remaining)
3181  *remaining = s;
3182 
3183  return text_size;
3184 }
3185 
3186 // 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)
3187 namespace ImStb
3188 {
3189 
3190 static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; }
3191 static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->TextW[idx]; }
3192 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; ImGuiContext& g = *GImGui; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); }
3193 static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; }
3196 {
3197  const ImWchar* text = obj->TextW.Data;
3198  const ImWchar* text_remaining = NULL;
3199  const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true);
3200  r->x0 = 0.0f;
3201  r->x1 = size.x;
3202  r->baseline_y_delta = size.y;
3203  r->ymin = 0.0f;
3204  r->ymax = size.y;
3205  r->num_chars = (int)(text_remaining - (text + line_start_idx));
3206 }
3207 
3208 static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
3209 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; }
3210 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; }
3211 #ifdef __APPLE__ // FIXME: Move setting to IO structure
3212 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; }
3213 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; }
3214 #else
3215 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; }
3216 #endif
3217 #define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
3218 #define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
3219 
3221 {
3222  ImWchar* dst = obj->TextW.Data + pos;
3223 
3224  // We maintain our buffer length in both UTF-8 and wchar formats
3225  obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);
3226  obj->CurLenW -= n;
3227 
3228  // Offset remaining text (FIXME-OPT: Use memmove)
3229  const ImWchar* src = obj->TextW.Data + pos + n;
3230  while (ImWchar c = *src++)
3231  *dst++ = c;
3232  *dst = '\0';
3233 }
3234 
3235 static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len)
3236 {
3237  const bool is_resizable = (obj->UserFlags & ImGuiInputTextFlags_CallbackResize) != 0;
3238  const int text_len = obj->CurLenW;
3239  IM_ASSERT(pos <= text_len);
3240 
3241  const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
3242  if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA))
3243  return false;
3244 
3245  // Grow internal buffer if needed
3246  if (new_text_len + text_len + 1 > obj->TextW.Size)
3247  {
3248  if (!is_resizable)
3249  return false;
3250  IM_ASSERT(text_len < obj->TextW.Size);
3251  obj->TextW.resize(text_len + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1);
3252  }
3253 
3254  ImWchar* text = obj->TextW.Data;
3255  if (pos != text_len)
3256  memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar));
3257  memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar));
3258 
3259  obj->CurLenW += new_text_len;
3260  obj->CurLenA += new_text_len_utf8;
3261  obj->TextW[obj->CurLenW] = '\0';
3262 
3263  return true;
3264 }
3265 
3266 // 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)
3267 #define STB_TEXTEDIT_K_LEFT 0x200000 // keyboard input to move cursor left
3268 #define STB_TEXTEDIT_K_RIGHT 0x200001 // keyboard input to move cursor right
3269 #define STB_TEXTEDIT_K_UP 0x200002 // keyboard input to move cursor up
3270 #define STB_TEXTEDIT_K_DOWN 0x200003 // keyboard input to move cursor down
3271 #define STB_TEXTEDIT_K_LINESTART 0x200004 // keyboard input to move cursor to start of line
3272 #define STB_TEXTEDIT_K_LINEEND 0x200005 // keyboard input to move cursor to end of line
3273 #define STB_TEXTEDIT_K_TEXTSTART 0x200006 // keyboard input to move cursor to start of text
3274 #define STB_TEXTEDIT_K_TEXTEND 0x200007 // keyboard input to move cursor to end of text
3275 #define STB_TEXTEDIT_K_DELETE 0x200008 // keyboard input to delete selection or character under cursor
3276 #define STB_TEXTEDIT_K_BACKSPACE 0x200009 // keyboard input to delete selection or character left of cursor
3277 #define STB_TEXTEDIT_K_UNDO 0x20000A // keyboard input to perform undo
3278 #define STB_TEXTEDIT_K_REDO 0x20000B // keyboard input to perform redo
3279 #define STB_TEXTEDIT_K_WORDLEFT 0x20000C // keyboard input to move cursor left one word
3280 #define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word
3281 #define STB_TEXTEDIT_K_SHIFT 0x400000
3282 
3283 #define STB_TEXTEDIT_IMPLEMENTATION
3284 #include "imstb_textedit.h"
3285 
3286 // stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling
3287 // the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?)
3289 {
3290  stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len);
3291  ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW);
3292  if (text_len <= 0)
3293  return;
3294  if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len))
3295  {
3296  state->cursor = text_len;
3297  state->has_preferred_x = 0;
3298  return;
3299  }
3300  IM_ASSERT(0); // Failed to insert character, normally shouldn't happen because of how we currently use stb_textedit_replace()
3301 }
3302 
3303 } // namespace ImStb
3304 
3306 {
3307  stb_textedit_key(this, &Stb, key);
3308  CursorFollow = true;
3309  CursorAnimReset();
3310 }
3311 
3313 {
3314  memset(this, 0, sizeof(*this));
3315 }
3316 
3317 // Public API to manipulate UTF-8 text
3318 // We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
3319 // FIXME: The existence of this rarely exercised code path is a bit of a nuisance.
3320 void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count)
3321 {
3322  IM_ASSERT(pos + bytes_count <= BufTextLen);
3323  char* dst = Buf + pos;
3324  const char* src = Buf + pos + bytes_count;
3325  while (char c = *src++)
3326  *dst++ = c;
3327  *dst = '\0';
3328 
3329  if (CursorPos + bytes_count >= pos)
3330  CursorPos -= bytes_count;
3331  else if (CursorPos >= pos)
3332  CursorPos = pos;
3334  BufDirty = true;
3335  BufTextLen -= bytes_count;
3336 }
3337 
3338 void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end)
3339 {
3340  const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
3341  const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
3342  if (new_text_len + BufTextLen >= BufSize)
3343  {
3344  if (!is_resizable)
3345  return;
3346 
3347  // Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the midly similar code (until we remove the U16 buffer alltogether!)
3348  ImGuiContext& g = *GImGui;
3349  ImGuiInputTextState* edit_state = &g.InputTextState;
3350  IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
3351  IM_ASSERT(Buf == edit_state->TextA.Data);
3352  int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
3353  edit_state->TextA.reserve(new_buf_size + 1);
3354  Buf = edit_state->TextA.Data;
3355  BufSize = edit_state->BufCapacityA = new_buf_size;
3356  }
3357 
3358  if (BufTextLen != pos)
3359  memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos));
3360  memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
3361  Buf[BufTextLen + new_text_len] = '\0';
3362 
3363  if (CursorPos >= pos)
3364  CursorPos += new_text_len;
3366  BufDirty = true;
3367  BufTextLen += new_text_len;
3368 }
3369 
3370 // Return false to discard a character.
3371 static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
3372 {
3373  unsigned int c = *p_char;
3374 
3375  // Filter non-printable (NB: isprint is unreliable! see #2467)
3376  if (c < 0x20)
3377  {
3378  bool pass = false;
3379  pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline));
3380  pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput));
3381  if (!pass)
3382  return false;
3383  }
3384 
3385  // We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817)
3386  if (c == 127)
3387  return false;
3388 
3389  // Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME)
3390  if (c >= 0xE000 && c <= 0xF8FF)
3391  return false;
3392 
3393  // Filter Unicode ranges we are not handling in this build.
3394  if (c > IM_UNICODE_CODEPOINT_MAX)
3395  return false;
3396 
3397  // Generic named filters
3399  {
3401  if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
3402  return false;
3403 
3405  if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E'))
3406  return false;
3407 
3409  if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))
3410  return false;
3411 
3413  if (c >= 'a' && c <= 'z')
3414  *p_char = (c += (unsigned int)('A'-'a'));
3415 
3417  if (ImCharIsBlankW(c))
3418  return false;
3419  }
3420 
3421  // Custom callback filter
3423  {
3424  ImGuiInputTextCallbackData callback_data;
3425  memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
3427  callback_data.EventChar = (ImWchar)c;
3428  callback_data.Flags = flags;
3429  callback_data.UserData = user_data;
3430  if (callback(&callback_data) != 0)
3431  return false;
3432  *p_char = callback_data.EventChar;
3433  if (!callback_data.EventChar)
3434  return false;
3435  }
3436 
3437  return true;
3438 }
3439 
3440 // Edit a string of text
3441 // - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!".
3442 // This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
3443 // Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator.
3444 // - 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.
3445 // - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h
3446 // (FIXME: Rather confusing and messy function, among the worse part of our codebase, expecting to rewrite a V2 at some point.. Partly because we are
3447 // doing UTF8 > U16 > UTF8 conversions on the go to easily interface with stb_textedit. Ideally should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188)
3448 bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data)
3449 {
3450  ImGuiWindow* window = GetCurrentWindow();
3451  if (window->SkipItems)
3452  return false;
3453 
3454  IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys)
3455  IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key)
3456 
3457  ImGuiContext& g = *GImGui;
3458  ImGuiIO& io = g.IO;
3459  const ImGuiStyle& style = g.Style;
3460 
3461  const bool RENDER_SELECTION_WHEN_INACTIVE = false;
3462  const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
3463  const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
3464  const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
3465  const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
3466  const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
3467  if (is_resizable)
3468  IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
3469 
3470  if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope,
3471  BeginGroup();
3472  const ImGuiID id = window->GetID(label);
3473  const ImVec2 label_size = CalcTextSize(label, NULL, true);
3474  const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line
3475  const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y);
3476 
3477  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
3478  const ImRect total_bb(frame_bb.Min, frame_bb.Min + total_size);
3479 
3480  ImGuiWindow* draw_window = window;
3481  ImVec2 inner_size = frame_size;
3482  if (is_multiline)
3483  {
3484  if (!ItemAdd(total_bb, id, &frame_bb))
3485  {
3486  ItemSize(total_bb, style.FramePadding.y);
3487  EndGroup();
3488  return false;
3489  }
3490 
3491  // We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug.
3496  bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding);
3497  PopStyleVar(3);
3498  PopStyleColor();
3499  if (!child_visible)
3500  {
3501  EndChild();
3502  EndGroup();
3503  return false;
3504  }
3505  draw_window = g.CurrentWindow; // Child window
3506  draw_window->DC.NavLayerActiveMaskNext |= draw_window->DC.NavLayerCurrentMask; // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it.
3507  inner_size.x -= draw_window->ScrollbarSizes.x;
3508  }
3509  else
3510  {
3511  ItemSize(total_bb, style.FramePadding.y);
3512  if (!ItemAdd(total_bb, id, &frame_bb))
3513  return false;
3514  }
3515  const bool hovered = ItemHoverable(frame_bb, id);
3516  if (hovered)
3517  g.MouseCursor = ImGuiMouseCursor_TextInput;
3518 
3519  // We are only allowed to access the state if we are already the active widget.
3521 
3522  const bool focus_requested = FocusableItemRegister(window, id);
3523  const bool focus_requested_by_code = focus_requested && (g.FocusRequestCurrWindow == window && g.FocusRequestCurrCounterRegular == window->DC.FocusCounterRegular);
3524  const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
3525 
3526  const bool user_clicked = hovered && io.MouseClicked[0];
3527  const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_NavKeyboard));
3528  const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
3529  const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
3530 
3531  bool clear_active_id = false;
3532  bool select_all = (g.ActiveId != id) && ((flags & ImGuiInputTextFlags_AutoSelectAll) != 0 || user_nav_input_start) && (!is_multiline);
3533 
3534  const bool init_make_active = (focus_requested || user_clicked || user_scroll_finish || user_nav_input_start);
3535  const bool init_state = (init_make_active || user_scroll_active);
3536  if (init_state && g.ActiveId != id)
3537  {
3538  // Access state even if we don't own it yet.
3539  state = &g.InputTextState;
3540  state->CursorAnimReset();
3541 
3542  // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
3543  // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
3544  const int buf_len = (int)strlen(buf);
3545  state->InitialTextA.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
3546  memcpy(state->InitialTextA.Data, buf, buf_len + 1);
3547 
3548  // Start edition
3549  const char* buf_end = NULL;
3550  state->TextW.resize(buf_size + 1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data is always pointing to at least an empty string.
3551  state->TextA.resize(0);
3552  state->TextAIsValid = false; // TextA is not valid yet (we will display buf until then)
3553  state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, buf_size, buf, NULL, &buf_end);
3554  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.
3555 
3556  // Preserve cursor position and undo/redo stack if we come back to same widget
3557  // FIXME: For non-readonly widgets we might be able to require that TextAIsValid && TextA == buf ? (untested) and discard undo stack if user buffer has changed.
3558  const bool recycle_state = (state->ID == id);
3559  if (recycle_state)
3560  {
3561  // Recycle existing cursor/selection/undo stack but clamp position
3562  // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
3563  state->CursorClamp();
3564  }
3565  else
3566  {
3567  state->ID = id;
3568  state->ScrollX = 0.0f;
3569  stb_textedit_initialize_state(&state->Stb, !is_multiline);
3570  if (!is_multiline && focus_requested_by_code)
3571  select_all = true;
3572  }
3574  state->Stb.insert_mode = 1;
3575  if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl)))
3576  select_all = true;
3577  }
3578 
3579  if (g.ActiveId != id && init_make_active)
3580  {
3581  IM_ASSERT(state && state->ID == id);
3582  SetActiveID(id, window);
3583  SetFocusID(id, window);
3584  FocusWindow(window);
3585 
3586  // Declare our inputs
3588  g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
3589  if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory))
3590  g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
3591  g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);
3592  g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Home) | ((ImU64)1 << ImGuiKey_End);
3593  if (is_multiline)
3594  g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_PageUp) | ((ImU64)1 << ImGuiKey_PageDown); // FIXME-NAV: Page up/down actually not supported yet by widget, but claim them ahead.
3595  if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character.
3596  g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Tab);
3597  }
3598 
3599  // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function)
3600  if (g.ActiveId == id && state == NULL)
3601  ClearActiveID();
3602 
3603  // Release focus when we click outside
3604  if (g.ActiveId == id && io.MouseClicked[0] && !init_state && !init_make_active) //-V560
3605  clear_active_id = true;
3606 
3607  // Lock the decision of whether we are going to take the path displaying the cursor or selection
3608  const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active);
3609  bool render_selection = state && state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
3610  bool value_changed = false;
3611  bool enter_pressed = false;
3612 
3613  // When read-only we always use the live data passed to the function
3614  // FIXME-OPT: Because our selection/cursor code currently needs the wide text we need to convert it when active, which is not ideal :(
3615  if (is_readonly && state != NULL && (render_cursor || render_selection))
3616  {
3617  const char* buf_end = NULL;
3618  state->TextW.resize(buf_size + 1);
3619  state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, buf, NULL, &buf_end);
3620  state->CurLenA = (int)(buf_end - buf);
3621  state->CursorClamp();
3622  render_selection &= state->HasSelection();
3623  }
3624 
3625  // Select the buffer to render.
3626  const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state && state->TextAIsValid;
3627  const bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
3628 
3629  // Password pushes a temporary font with only a fallback glyph
3630  if (is_password && !is_displaying_hint)
3631  {
3632  const ImFontGlyph* glyph = g.Font->FindGlyph('*');
3633  ImFont* password_font = &g.InputTextPasswordFont;
3634  password_font->FontSize = g.Font->FontSize;
3635  password_font->Scale = g.Font->Scale;
3636  password_font->DisplayOffset = g.Font->DisplayOffset;
3637  password_font->Ascent = g.Font->Ascent;
3638  password_font->Descent = g.Font->Descent;
3639  password_font->ContainerAtlas = g.Font->ContainerAtlas;
3640  password_font->FallbackGlyph = glyph;
3641  password_font->FallbackAdvanceX = glyph->AdvanceX;
3642  IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty());
3643  PushFont(password_font);
3644  }
3645 
3646  // Process mouse inputs and character inputs
3647  int backup_current_text_length = 0;
3648  if (g.ActiveId == id)
3649  {
3650  IM_ASSERT(state != NULL);
3651  backup_current_text_length = state->CurLenA;
3652  state->BufCapacityA = buf_size;
3653  state->UserFlags = flags;
3654  state->UserCallback = callback;
3655  state->UserCallbackData = callback_user_data;
3656 
3657  // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
3658  // Down the line we should have a cleaner library-wide concept of Selected vs Active.
3659  g.ActiveIdAllowOverlap = !io.MouseDown[0];
3660  g.WantTextInputNextFrame = 1;
3661 
3662  // Edit in progress
3663  const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
3664  const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f));
3665 
3666  const bool is_osx = io.ConfigMacOSXBehaviors;
3667  if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0]))
3668  {
3669  state->SelectAll();
3670  state->SelectedAllMouseLock = true;
3671  }
3672  else if (hovered && is_osx && io.MouseDoubleClicked[0])
3673  {
3674  // Double-click select a word only, OS X style (by simulating keystrokes)
3677  }
3678  else if (io.MouseClicked[0] && !state->SelectedAllMouseLock)
3679  {
3680  if (hovered)
3681  {
3682  stb_textedit_click(state, &state->Stb, mouse_x, mouse_y);
3683  state->CursorAnimReset();
3684  }
3685  }
3686  else if (io.MouseDown[0] && !state->SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f))
3687  {
3688  stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y);
3689  state->CursorAnimReset();
3690  state->CursorFollow = true;
3691  }
3692  if (state->SelectedAllMouseLock && !io.MouseDown[0])
3693  state->SelectedAllMouseLock = false;
3694 
3695  // It is ill-defined whether the back-end needs to send a \t character when pressing the TAB keys.
3696  // Win32 and GLFW naturally do it but not SDL.
3697  const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper);
3698  if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !ignore_char_inputs && !io.KeyShift && !is_readonly)
3699  if (!io.InputQueueCharacters.contains('\t'))
3700  {
3701  unsigned int c = '\t'; // Insert TAB
3702  if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
3703  state->OnKeyPressed((int)c);
3704  }
3705 
3706  // Process regular text input (before we check for Return because using some IME will effectively send a Return?)
3707  // 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.
3708  if (io.InputQueueCharacters.Size > 0)
3709  {
3710  if (!ignore_char_inputs && !is_readonly && !user_nav_input_start)
3711  for (int n = 0; n < io.InputQueueCharacters.Size; n++)
3712  {
3713  // Insert character if they pass filtering
3714  unsigned int c = (unsigned int)io.InputQueueCharacters[n];
3715  if (c == '\t' && io.KeyShift)
3716  continue;
3717  if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
3718  state->OnKeyPressed((int)c);
3719  }
3720 
3721  // Consume characters
3723  }
3724  }
3725 
3726  // Process other shortcuts/key-presses
3727  bool cancel_edit = false;
3728  if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id)
3729  {
3730  IM_ASSERT(state != NULL);
3731  const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
3732  const bool is_osx = io.ConfigMacOSXBehaviors;
3733  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
3734  const bool is_osx_shift_shortcut = is_osx && io.KeySuper && io.KeyShift && !io.KeyCtrl && !io.KeyAlt;
3735  const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
3736  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
3737  const bool is_ctrl_key_only = io.KeyCtrl && !io.KeyShift && !io.KeyAlt && !io.KeySuper;
3738  const bool is_shift_key_only = io.KeyShift && !io.KeyCtrl && !io.KeyAlt && !io.KeySuper;
3739 
3740  const bool is_cut = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Delete))) && !is_readonly && !is_password && (!is_multiline || state->HasSelection());
3741  const bool is_copy = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_password && (!is_multiline || state->HasSelection());
3742  const bool is_paste = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_readonly;
3743  const bool is_undo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Z)) && !is_readonly && is_undoable);
3744  const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && !is_readonly && is_undoable;
3745 
3746  if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
3747  else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
3748  else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
3749  else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
3751  else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
3752  else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
3753  else if (IsKeyPressedMap(ImGuiKey_Backspace) && !is_readonly)
3754  {
3755  if (!state->HasSelection())
3756  {
3757  if (is_wordmove_key_down)
3759  else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl)
3761  }
3762  state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
3763  }
3765  {
3766  bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
3767  if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl))
3768  {
3769  enter_pressed = clear_active_id = true;
3770  }
3771  else if (!is_readonly)
3772  {
3773  unsigned int c = '\n'; // Insert new line
3774  if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
3775  state->OnKeyPressed((int)c);
3776  }
3777  }
3778  else if (IsKeyPressedMap(ImGuiKey_Escape))
3779  {
3780  clear_active_id = cancel_edit = true;
3781  }
3782  else if (is_undo || is_redo)
3783  {
3785  state->ClearSelection();
3786  }
3787  else if (is_shortcut_key && IsKeyPressedMap(ImGuiKey_A))
3788  {
3789  state->SelectAll();
3790  state->CursorFollow = true;
3791  }
3792  else if (is_cut || is_copy)
3793  {
3794  // Cut, Copy
3795  if (io.SetClipboardTextFn)
3796  {
3797  const int ib = state->HasSelection() ? ImMin(state->Stb.select_start, state->Stb.select_end) : 0;
3798  const int ie = state->HasSelection() ? ImMax(state->Stb.select_start, state->Stb.select_end) : state->CurLenW;
3799  const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1;
3800  char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char));
3801  ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie);
3802  SetClipboardText(clipboard_data);
3803  MemFree(clipboard_data);
3804  }
3805  if (is_cut)
3806  {
3807  if (!state->HasSelection())
3808  state->SelectAll();
3809  state->CursorFollow = true;
3810  stb_textedit_cut(state, &state->Stb);
3811  }
3812  }
3813  else if (is_paste)
3814  {
3815  if (const char* clipboard = GetClipboardText())
3816  {
3817  // Filter pasted buffer
3818  const int clipboard_len = (int)strlen(clipboard);
3819  ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len+1) * sizeof(ImWchar));
3820  int clipboard_filtered_len = 0;
3821  for (const char* s = clipboard; *s; )
3822  {
3823  unsigned int c;
3824  s += ImTextCharFromUtf8(&c, s, NULL);
3825  if (c == 0)
3826  break;
3827  if (!InputTextFilterCharacter(&c, flags, callback, callback_user_data))
3828  continue;
3829  clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
3830  }
3831  clipboard_filtered[clipboard_filtered_len] = 0;
3832  if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation
3833  {
3834  stb_textedit_paste(state, &state->Stb, clipboard_filtered, clipboard_filtered_len);
3835  state->CursorFollow = true;
3836  }
3837  MemFree(clipboard_filtered);
3838  }
3839  }
3840 
3841  // Update render selection flag after events have been handled, so selection highlight can be displayed during the same frame.
3842  render_selection |= state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
3843  }
3844 
3845  // Process callbacks and apply result back to user's buffer.
3846  if (g.ActiveId == id)
3847  {
3848  IM_ASSERT(state != NULL);
3849  const char* apply_new_text = NULL;
3850  int apply_new_text_length = 0;
3851  if (cancel_edit)
3852  {
3853  // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
3854  if (!is_readonly && strcmp(buf, state->InitialTextA.Data) != 0)
3855  {
3856  // Push records into the undo stack so we can CTRL+Z the revert operation itself
3857  apply_new_text = state->InitialTextA.Data;
3858  apply_new_text_length = state->InitialTextA.Size - 1;
3859  ImVector<ImWchar> w_text;
3860  if (apply_new_text_length > 0)
3861  {
3862  w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1);
3863  ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length);
3864  }
3865  stb_textedit_replace(state, &state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0);
3866  }
3867  }
3868 
3869  // 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.
3870  // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail.
3871  // This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize).
3872  bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
3873  if (apply_edit_back_to_user_buffer)
3874  {
3875  // Apply new value immediately - copy modified buffer back
3876  // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
3877  // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect.
3878  // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.
3879  if (!is_readonly)
3880  {
3881  state->TextAIsValid = true;
3882  state->TextA.resize(state->TextW.Size * 4 + 1);
3883  ImTextStrToUtf8(state->TextA.Data, state->TextA.Size, state->TextW.Data, NULL);
3884  }
3885 
3886  // User callback
3888  {
3889  IM_ASSERT(callback != NULL);
3890 
3891  // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
3892  ImGuiInputTextFlags event_flag = 0;
3893  ImGuiKey event_key = ImGuiKey_COUNT;
3895  {
3897  event_key = ImGuiKey_Tab;
3898  }
3900  {
3902  event_key = ImGuiKey_UpArrow;
3903  }
3905  {
3907  event_key = ImGuiKey_DownArrow;
3908  }
3911 
3912  if (event_flag)
3913  {
3914  ImGuiInputTextCallbackData callback_data;
3915  memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
3916  callback_data.EventFlag = event_flag;
3917  callback_data.Flags = flags;
3918  callback_data.UserData = callback_user_data;
3919 
3920  callback_data.EventKey = event_key;
3921  callback_data.Buf = state->TextA.Data;
3922  callback_data.BufTextLen = state->CurLenA;
3923  callback_data.BufSize = state->BufCapacityA;
3924  callback_data.BufDirty = false;
3925 
3926  // 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)
3927  ImWchar* text = state->TextW.Data;
3928  const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb.cursor);
3929  const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_start);
3930  const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_end);
3931 
3932  // Call user code
3933  callback(&callback_data);
3934 
3935  // Read back what user may have modified
3936  IM_ASSERT(callback_data.Buf == state->TextA.Data); // Invalid to modify those fields
3937  IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
3938  IM_ASSERT(callback_data.Flags == flags);
3939  if (callback_data.CursorPos != utf8_cursor_pos) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; }
3940  if (callback_data.SelectionStart != utf8_selection_start) { state->Stb.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); }
3941  if (callback_data.SelectionEnd != utf8_selection_end) { state->Stb.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
3942  if (callback_data.BufDirty)
3943  {
3944  IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
3945  if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
3946  state->TextW.resize(state->TextW.Size + (callback_data.BufTextLen - backup_current_text_length));
3947  state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, callback_data.Buf, NULL);
3948  state->CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
3949  state->CursorAnimReset();
3950  }
3951  }
3952  }
3953 
3954  // Will copy result string if modified
3955  if (!is_readonly && strcmp(state->TextA.Data, buf) != 0)
3956  {
3957  apply_new_text = state->TextA.Data;
3958  apply_new_text_length = state->CurLenA;
3959  }
3960  }
3961 
3962  // Copy result to user buffer
3963  if (apply_new_text)
3964  {
3965  // We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
3966  // of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
3967  // without any storage on user's side.
3968  IM_ASSERT(apply_new_text_length >= 0);
3969  if (is_resizable)
3970  {
3971  ImGuiInputTextCallbackData callback_data;
3973  callback_data.Flags = flags;
3974  callback_data.Buf = buf;
3975  callback_data.BufTextLen = apply_new_text_length;
3976  callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
3977  callback_data.UserData = callback_user_data;
3978  callback(&callback_data);
3979  buf = callback_data.Buf;
3980  buf_size = callback_data.BufSize;
3981  apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1);
3982  IM_ASSERT(apply_new_text_length <= buf_size);
3983  }
3984  //IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length);
3985 
3986  // If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
3987  ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
3988  value_changed = true;
3989  }
3990 
3991  // Clear temporary user storage
3992  state->UserFlags = 0;
3993  state->UserCallback = NULL;
3994  state->UserCallbackData = NULL;
3995  }
3996 
3997  // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
3998  if (clear_active_id && g.ActiveId == id)
3999  ClearActiveID();
4000 
4001  // Render frame
4002  if (!is_multiline)
4003  {
4004  RenderNavHighlight(frame_bb, id);
4005  RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
4006  }
4007 
4008  const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + inner_size.x, frame_bb.Min.y + inner_size.y); // Not using frame_bb.Max because we have adjusted size
4009  ImVec2 draw_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding;
4010  ImVec2 text_size(0.0f, 0.0f);
4011 
4012  // Set upper limit of single-line InputTextEx() at 2 million characters strings. The current pathological worst case is a long line
4013  // without any carriage return, which would makes ImFont::RenderText() reserve too many vertices and probably crash. Avoid it altogether.
4014  // Note that we only use this limit on single-line InputText(), so a pathologically large line on a InputTextMultiline() would still crash.
4015  const int buf_display_max_length = 2 * 1024 * 1024;
4016  const char* buf_display = buf_display_from_state ? state->TextA.Data : buf; //-V595
4017  const char* buf_display_end = NULL; // We have specialized paths below for setting the length
4018  if (is_displaying_hint)
4019  {
4020  buf_display = hint;
4021  buf_display_end = hint + strlen(hint);
4022  }
4023 
4024  // Render text. We currently only render selection when the widget is active or while scrolling.
4025  // FIXME: We could remove the '&& render_cursor' to keep rendering selection when inactive.
4026  if (render_cursor || render_selection)
4027  {
4028  IM_ASSERT(state != NULL);
4029  if (!is_displaying_hint)
4030  buf_display_end = buf_display + state->CurLenA;
4031 
4032  // Render text (with cursor and selection)
4033  // This is going to be messy. We need to:
4034  // - Display the text (this alone can be more easily clipped)
4035  // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation)
4036  // - Measure text height (for scrollbar)
4037  // 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)
4038  // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
4039  const ImWchar* text_begin = state->TextW.Data;
4040  ImVec2 cursor_offset, select_start_offset;
4041 
4042  {
4043  // Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions.
4044  const ImWchar* searches_input_ptr[2] = { NULL, NULL };
4045  int searches_result_line_no[2] = { -1000, -1000 };
4046  int searches_remaining = 0;
4047  if (render_cursor)
4048  {
4049  searches_input_ptr[0] = text_begin + state->Stb.cursor;
4050  searches_result_line_no[0] = -1;
4051  searches_remaining++;
4052  }
4053  if (render_selection)
4054  {
4055  searches_input_ptr[1] = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end);
4056  searches_result_line_no[1] = -1;
4057  searches_remaining++;
4058  }
4059 
4060  // Iterate all lines to find our line numbers
4061  // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
4062  searches_remaining += is_multiline ? 1 : 0;
4063  int line_count = 0;
4064  //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-bit
4065  for (const ImWchar* s = text_begin; *s != 0; s++)
4066  if (*s == '\n')
4067  {
4068  line_count++;
4069  if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; }
4070  if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; }
4071  }
4072  line_count++;
4073  if (searches_result_line_no[0] == -1)
4074  searches_result_line_no[0] = line_count;
4075  if (searches_result_line_no[1] == -1)
4076  searches_result_line_no[1] = line_count;
4077 
4078  // Calculate 2d position by finding the beginning of the line and measuring distance
4079  cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
4080  cursor_offset.y = searches_result_line_no[0] * g.FontSize;
4081  if (searches_result_line_no[1] >= 0)
4082  {
4083  select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
4084  select_start_offset.y = searches_result_line_no[1] * g.FontSize;
4085  }
4086 
4087  // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224)
4088  if (is_multiline)
4089  text_size = ImVec2(inner_size.x, line_count * g.FontSize);
4090  }
4091 
4092  // Scroll
4093  if (render_cursor && state->CursorFollow)
4094  {
4095  // Horizontal scroll in chunks of quarter width
4097  {
4098  const float scroll_increment_x = inner_size.x * 0.25f;
4099  if (cursor_offset.x < state->ScrollX)
4100  state->ScrollX = IM_FLOOR(ImMax(0.0f, cursor_offset.x - scroll_increment_x));
4101  else if (cursor_offset.x - inner_size.x >= state->ScrollX)
4102  state->ScrollX = IM_FLOOR(cursor_offset.x - inner_size.x + scroll_increment_x);
4103  }
4104  else
4105  {
4106  state->ScrollX = 0.0f;
4107  }
4108 
4109  // Vertical scroll
4110  if (is_multiline)
4111  {
4112  float scroll_y = draw_window->Scroll.y;
4113  if (cursor_offset.y - g.FontSize < scroll_y)
4114  scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize);
4115  else if (cursor_offset.y - inner_size.y >= scroll_y)
4116  scroll_y = cursor_offset.y - inner_size.y;
4117  draw_pos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag
4118  draw_window->Scroll.y = scroll_y;
4119  }
4120 
4121  state->CursorFollow = false;
4122  }
4123 
4124  // Draw selection
4125  const ImVec2 draw_scroll = ImVec2(state->ScrollX, 0.0f);
4126  if (render_selection)
4127  {
4128  const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end);
4129  const ImWchar* text_selected_end = text_begin + ImMax(state->Stb.select_start, state->Stb.select_end);
4130 
4131  ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests.
4132  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.
4133  float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
4134  ImVec2 rect_pos = draw_pos + select_start_offset - draw_scroll;
4135  for (const ImWchar* p = text_selected_begin; p < text_selected_end; )
4136  {
4137  if (rect_pos.y > clip_rect.w + g.FontSize)
4138  break;
4139  if (rect_pos.y < clip_rect.y)
4140  {
4141  //p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p); // FIXME-OPT: Could use this when wchar_t are 16-bit
4142  //p = p ? p + 1 : text_selected_end;
4143  while (p < text_selected_end)
4144  if (*p++ == '\n')
4145  break;
4146  }
4147  else
4148  {
4149  ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true);
4150  if (rect_size.x <= 0.0f) rect_size.x = IM_FLOOR(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
4151  ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn));
4152  rect.ClipWith(clip_rect);
4153  if (rect.Overlaps(clip_rect))
4154  draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
4155  }
4156  rect_pos.x = draw_pos.x - draw_scroll.x;
4157  rect_pos.y += g.FontSize;
4158  }
4159  }
4160 
4161  // We test for 'buf_display_max_length' as a way to avoid some pathological cases (e.g. single-line 1 MB string) which would make ImDrawList crash.
4162  if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
4163  {
4164  ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
4165  draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
4166  }
4167 
4168  // Draw blinking cursor
4169  if (render_cursor)
4170  {
4171  state->CursorAnim += io.DeltaTime;
4172  bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
4173  ImVec2 cursor_screen_pos = draw_pos + cursor_offset - draw_scroll;
4174  ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
4175  if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
4176  draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
4177 
4178  // 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.)
4179  if (!is_readonly)
4180  g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize);
4181  }
4182  }
4183  else
4184  {
4185  // Render text only (no selection, no cursor)
4186  if (is_multiline)
4187  text_size = ImVec2(inner_size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width
4188  else if (!is_displaying_hint && g.ActiveId == id)
4189  buf_display_end = buf_display + state->CurLenA;
4190  else if (!is_displaying_hint)
4191  buf_display_end = buf_display + strlen(buf_display);
4192 
4193  if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
4194  {
4195  ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
4196  draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
4197  }
4198  }
4199 
4200  if (is_multiline)
4201  {
4202  Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line
4203  EndChild();
4204  EndGroup();
4205  }
4206 
4207  if (is_password && !is_displaying_hint)
4208  PopFont();
4209 
4210  // Log as text
4211  if (g.LogEnabled && !(is_password && !is_displaying_hint))
4212  LogRenderedText(&draw_pos, buf_display, buf_display_end);
4213 
4214  if (label_size.x > 0)
4215  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
4216 
4217  if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited))
4218  MarkItemEdited(id);
4219 
4222  return enter_pressed;
4223  else
4224  return value_changed;
4225 }
4226 
4227 //-------------------------------------------------------------------------
4228 // [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc.
4229 //-------------------------------------------------------------------------
4230 // - ColorEdit3()
4231 // - ColorEdit4()
4232 // - ColorPicker3()
4233 // - RenderColorRectWithAlphaCheckerboard() [Internal]
4234 // - ColorPicker4()
4235 // - ColorButton()
4236 // - SetColorEditOptions()
4237 // - ColorTooltip() [Internal]
4238 // - ColorEditOptionsPopup() [Internal]
4239 // - ColorPickerOptionsPopup() [Internal]
4240 //-------------------------------------------------------------------------
4241 
4242 bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags)
4243 {
4245 }
4246 
4247 // Edit colors components (each component in 0.0f..1.0f range).
4248 // See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
4249 // 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.
4250 bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags)
4251 {
4252  ImGuiWindow* window = GetCurrentWindow();
4253  if (window->SkipItems)
4254  return false;
4255 
4256  ImGuiContext& g = *GImGui;
4257  const ImGuiStyle& style = g.Style;
4258  const float square_sz = GetFrameHeight();
4259  const float w_full = CalcItemWidth();
4260  const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
4261  const float w_inputs = w_full - w_button;
4262  const char* label_display_end = FindRenderedTextEnd(label);
4263  g.NextItemData.ClearFlags();
4264 
4265  BeginGroup();
4266  PushID(label);
4267 
4268  // If we're not showing any slider there's no point in doing any HSV conversions
4269  const ImGuiColorEditFlags flags_untouched = flags;
4272 
4273  // Context menu: display and modify options (before defaults are applied)
4276 
4277  // Read stored options
4279  flags |= (g.ColorEditOptions & ImGuiColorEditFlags__DisplayMask);
4281  flags |= (g.ColorEditOptions & ImGuiColorEditFlags__DataTypeMask);
4283  flags |= (g.ColorEditOptions & ImGuiColorEditFlags__PickerMask);
4285  flags |= (g.ColorEditOptions & ImGuiColorEditFlags__InputMask);
4287  IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DisplayMask)); // Check that only 1 is selected
4288  IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__InputMask)); // Check that only 1 is selected
4289 
4290  const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0;
4291  const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0;
4292  const int components = alpha ? 4 : 3;
4293 
4294  // Convert to the formats we need
4295  float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f };
4297  ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
4299  {
4300  // Hue is lost when converting from greyscale rgb (saturation=0). Restore it.
4301  ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
4302  if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0)
4303  {
4304  if (f[1] == 0)
4305  f[0] = g.ColorEditLastHue;
4306  if (f[2] == 0)
4307  f[1] = g.ColorEditLastSat;
4308  }
4309  }
4311 
4312  bool value_changed = false;
4313  bool value_changed_as_float = false;
4314 
4315  const ImVec2 pos = window->DC.CursorPos;
4316  const float inputs_offset_x = (style.ColorButtonPosition == ImGuiDir_Left) ? w_button : 0.0f;
4317  window->DC.CursorPos.x = pos.x + inputs_offset_x;
4318 
4320  {
4321  // RGB/HSV 0..255 Sliders
4322  const float w_item_one = ImMax(1.0f, IM_FLOOR((w_inputs - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
4323  const float w_item_last = ImMax(1.0f, IM_FLOOR(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
4324 
4325  const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x);
4326  static const char* ids[4] = { "##X", "##Y", "##Z", "##W" };
4327  static const char* fmt_table_int[3][4] =
4328  {
4329  { "%3d", "%3d", "%3d", "%3d" }, // Short display
4330  { "R:%3d", "G:%3d", "B:%3d", "A:%3d" }, // Long display for RGBA
4331  { "H:%3d", "S:%3d", "V:%3d", "A:%3d" } // Long display for HSVA
4332  };
4333  static const char* fmt_table_float[3][4] =
4334  {
4335  { "%0.3f", "%0.3f", "%0.3f", "%0.3f" }, // Short display
4336  { "R:%0.3f", "G:%0.3f", "B:%0.3f", "A:%0.3f" }, // Long display for RGBA
4337  { "H:%0.3f", "S:%0.3f", "V:%0.3f", "A:%0.3f" } // Long display for HSVA
4338  };
4339  const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1;
4340 
4341  for (int n = 0; n < components; n++)
4342  {
4343  if (n > 0)
4344  SameLine(0, style.ItemInnerSpacing.x);
4345  SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last);
4346 
4347  // FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0.
4349  {
4350  value_changed |= DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
4351  value_changed_as_float |= value_changed;
4352  }
4353  else
4354  {
4355  value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);
4356  }
4358  OpenPopupOnItemClick("context");
4359  }
4360  }
4362  {
4363  // RGB Hexadecimal Input
4364  char buf[64];
4365  if (alpha)
4366  ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255), ImClamp(i[3],0,255));
4367  else
4368  ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255));
4369  SetNextItemWidth(w_inputs);
4371  {
4372  value_changed = true;
4373  char* p = buf;
4374  while (*p == '#' || ImCharIsBlankA(*p))
4375  p++;
4376  i[0] = i[1] = i[2] = i[3] = 0;
4377  if (alpha)
4378  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)
4379  else
4380  sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
4381  }
4383  OpenPopupOnItemClick("context");
4384  }
4385 
4386  ImGuiWindow* picker_active_window = NULL;
4388  {
4389  const float button_offset_x = ((flags & ImGuiColorEditFlags_NoInputs) || (style.ColorButtonPosition == ImGuiDir_Left)) ? 0.0f : w_inputs + style.ItemInnerSpacing.x;
4390  window->DC.CursorPos = ImVec2(pos.x + button_offset_x, pos.y);
4391 
4392  const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f);
4393  if (ColorButton("##ColorButton", col_v4, flags))
4394  {
4396  {
4397  // Store current color and open a picker
4398  g.ColorPickerRef = col_v4;
4399  OpenPopup("picker");
4400  SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1,style.ItemSpacing.y));
4401  }
4402  }
4404  OpenPopupOnItemClick("context");
4405 
4406  if (BeginPopup("picker"))
4407  {
4408  picker_active_window = g.CurrentWindow;
4409  if (label != label_display_end)
4410  {
4411  TextEx(label, label_display_end);
4412  Spacing();
4413  }
4415  ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__DisplayMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
4416  SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
4417  value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
4418  EndPopup();
4419  }
4420  }
4421 
4422  if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel))
4423  {
4424  const float text_offset_x = (flags & ImGuiColorEditFlags_NoInputs) ? w_button : w_full + style.ItemInnerSpacing.x;
4425  window->DC.CursorPos = ImVec2(pos.x + text_offset_x, pos.y + style.FramePadding.y);
4426  TextEx(label, label_display_end);
4427  }
4428 
4429  // Convert back
4430  if (value_changed && picker_active_window == NULL)
4431  {
4432  if (!value_changed_as_float)
4433  for (int n = 0; n < 4; n++)
4434  f[n] = i[n] / 255.0f;
4436  {
4437  g.ColorEditLastHue = f[0];
4438  g.ColorEditLastSat = f[1];
4439  ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
4440  memcpy(g.ColorEditLastColor, f, sizeof(float) * 3);
4441  }
4443  ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
4444 
4445  col[0] = f[0];
4446  col[1] = f[1];
4447  col[2] = f[2];
4448  if (alpha)
4449  col[3] = f[3];
4450  }
4451 
4452  PopID();
4453  EndGroup();
4454 
4455  // Drag and Drop Target
4456  // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.
4458  {
4459  bool accepted_drag_drop = false;
4461  {
4462  memcpy((float*)col, payload->Data, sizeof(float) * 3); // Preserve alpha if any //-V512
4463  value_changed = accepted_drag_drop = true;
4464  }
4466  {
4467  memcpy((float*)col, payload->Data, sizeof(float) * components);
4468  value_changed = accepted_drag_drop = true;
4469  }
4470 
4471  // Drag-drop payloads are always RGB
4472  if (accepted_drag_drop && (flags & ImGuiColorEditFlags_InputHSV))
4473  ColorConvertRGBtoHSV(col[0], col[1], col[2], col[0], col[1], col[2]);
4475  }
4476 
4477  // When picker is being actively used, use its active id so IsItemActive() will function on ColorEdit4().
4478  if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window)
4479  window->DC.LastItemId = g.ActiveId;
4480 
4481  if (value_changed)
4482  MarkItemEdited(window->DC.LastItemId);
4483 
4484  return value_changed;
4485 }
4486 
4487 bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags)
4488 {
4489  float col4[4] = { col[0], col[1], col[2], 1.0f };
4491  return false;
4492  col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2];
4493  return true;
4494 }
4495 
4496 // Helper for ColorPicker4()
4497 static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha)
4498 {
4499  ImU32 alpha8 = IM_F32_TO_INT8_SAT(alpha);
4500  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(0,0,0,alpha8));
4501  ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32(255,255,255,alpha8));
4502  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(0,0,0,alpha8));
4503  ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32(255,255,255,alpha8));
4504 }
4505 
4506 // Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
4507 // (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.)
4508 // 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..)
4509 // FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0)
4510 bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)
4511 {
4512  ImGuiContext& g = *GImGui;
4513  ImGuiWindow* window = GetCurrentWindow();
4514  if (window->SkipItems)
4515  return false;
4516 
4517  ImDrawList* draw_list = window->DrawList;
4518  ImGuiStyle& style = g.Style;
4519  ImGuiIO& io = g.IO;
4520 
4521  const float width = CalcItemWidth();
4522  g.NextItemData.ClearFlags();
4523 
4524  PushID(label);
4525  BeginGroup();
4526 
4529 
4530  // Context menu: display and store options.
4533 
4534  // Read stored options
4539  IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__PickerMask)); // Check that only 1 is selected
4540  IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__InputMask)); // Check that only 1 is selected
4542  flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);
4543 
4544  // Setup
4545  int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4;
4547  ImVec2 picker_pos = window->DC.CursorPos;
4548  float square_sz = GetFrameHeight();
4549  float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars
4550  float sv_picker_size = ImMax(bars_width * 1, width - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
4551  float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
4552  float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
4553  float bars_triangles_half_sz = IM_FLOOR(bars_width * 0.20f);
4554 
4555  float backup_initial_col[4];
4556  memcpy(backup_initial_col, col, components * sizeof(float));
4557 
4558  float wheel_thickness = sv_picker_size * 0.08f;
4559  float wheel_r_outer = sv_picker_size * 0.50f;
4560  float wheel_r_inner = wheel_r_outer - wheel_thickness;
4561  ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size*0.5f);
4562 
4563  // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic.
4564  float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);
4565  ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point.
4566  ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point.
4567  ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point.
4568 
4569  float H = col[0], S = col[1], V = col[2];
4570  float R = col[0], G = col[1], B = col[2];
4572  {
4573  // Hue is lost when converting from greyscale rgb (saturation=0). Restore it.
4574  ColorConvertRGBtoHSV(R, G, B, H, S, V);
4575  if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0)
4576  {
4577  if (S == 0)
4578  H = g.ColorEditLastHue;
4579  if (V == 0)
4580  S = g.ColorEditLastSat;
4581  }
4582  }
4584  {
4585  ColorConvertHSVtoRGB(H, S, V, R, G, B);
4586  }
4587 
4588  bool value_changed = false, value_changed_h = false, value_changed_sv = false;
4589 
4592  {
4593  // Hue wheel + SV triangle logic
4594  InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));
4595  if (IsItemActive())
4596  {
4597  ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
4598  ImVec2 current_off = g.IO.MousePos - wheel_center;
4599  float initial_dist2 = ImLengthSqr(initial_off);
4600  if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1))
4601  {
4602  // Interactive with Hue wheel
4603  H = ImAtan2(current_off.y, current_off.x) / IM_PI*0.5f;
4604  if (H < 0.0f)
4605  H += 1.0f;
4606  value_changed = value_changed_h = true;
4607  }
4608  float cos_hue_angle = ImCos(-H * 2.0f * IM_PI);
4609  float sin_hue_angle = ImSin(-H * 2.0f * IM_PI);
4610  if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle)))
4611  {
4612  // Interacting with SV triangle
4613  ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle);
4614  if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated))
4615  current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);
4616  float uu, vv, ww;
4617  ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww);
4618  V = ImClamp(1.0f - vv, 0.0001f, 1.0f);
4619  S = ImClamp(uu / V, 0.0001f, 1.0f);
4620  value_changed = value_changed_sv = true;
4621  }
4622  }
4624  OpenPopupOnItemClick("context");
4625  }
4627  {
4628  // SV rectangle logic
4629  InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
4630  if (IsItemActive())
4631  {
4632  S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size-1));
4633  V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
4634  value_changed = value_changed_sv = true;
4635  }
4637  OpenPopupOnItemClick("context");
4638 
4639  // Hue bar logic
4640  SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
4641  InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
4642  if (IsItemActive())
4643  {
4644  H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
4645  value_changed = value_changed_h = true;
4646  }
4647  }
4648 
4649  // Alpha bar logic
4650  if (alpha_bar)
4651  {
4652  SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y));
4653  InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size));
4654  if (IsItemActive())
4655  {
4656  col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
4657  value_changed = true;
4658  }
4659  }
4660  PopItemFlag(); // ImGuiItemFlags_NoNav
4661 
4663  {
4664  SameLine(0, style.ItemInnerSpacing.x);
4665  BeginGroup();
4666  }
4667 
4669  {
4670  const char* label_display_end = FindRenderedTextEnd(label);
4671  if (label != label_display_end)
4672  {
4674  SameLine(0, style.ItemInnerSpacing.x);
4675  TextEx(label, label_display_end);
4676  }
4677  }
4678 
4680  {
4682  ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
4684  Text("Current");
4685 
4687  ColorButton("##current", col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2));
4688  if (ref_col != NULL)
4689  {
4690  Text("Original");
4691  ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]);
4692  if (ColorButton("##original", ref_col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2)))
4693  {
4694  memcpy(col, ref_col, components * sizeof(float));
4695  value_changed = true;
4696  }
4697  }
4698  PopItemFlag();
4699  EndGroup();
4700  }
4701 
4702  // Convert back color to RGB
4703  if (value_changed_h || value_changed_sv)
4704  {
4706  {
4707  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]);
4708  g.ColorEditLastHue = H;
4709  g.ColorEditLastSat = S;
4710  memcpy(g.ColorEditLastColor, col, sizeof(float) * 3);
4711  }
4713  {
4714  col[0] = H;
4715  col[1] = S;
4716  col[2] = V;
4717  }
4718  }
4719 
4720  // R,G,B and H,S,V slider color editor
4721  bool value_changed_fix_hue_wrap = false;
4722  if ((flags & ImGuiColorEditFlags_NoInputs) == 0)
4723  {
4724  PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);
4726  ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker;
4728  if (ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_DisplayRGB))
4729  {
4730  // FIXME: Hackily differenciating using the DragInt (ActiveId != 0 && !ActiveIdAllowOverlap) vs. using the InputText or DropTarget.
4731  // 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)
4732  value_changed_fix_hue_wrap = (g.ActiveId != 0 && !g.ActiveIdAllowOverlap);
4733  value_changed = true;
4734  }
4736  value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_DisplayHSV);
4738  value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_DisplayHex);
4739  PopItemWidth();
4740  }
4741 
4742  // Try to cancel hue wrap (after ColorEdit4 call), if any
4743  if (value_changed_fix_hue_wrap && (flags & ImGuiColorEditFlags_InputRGB))
4744  {
4745  float new_H, new_S, new_V;
4746  ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V);
4747  if (new_H <= 0 && H > 0)
4748  {
4749  if (new_V <= 0 && V != new_V)
4750  ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]);
4751  else if (new_S <= 0)
4752  ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]);
4753  }
4754  }
4755 
4756  if (value_changed)
4757  {
4759  {
4760  R = col[0];
4761  G = col[1];
4762  B = col[2];
4763  ColorConvertRGBtoHSV(R, G, B, H, S, V);
4764  if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) // Fix local Hue as display below will use it immediately.
4765  {
4766  if (S == 0)
4767  H = g.ColorEditLastHue;
4768  if (V == 0)
4769  S = g.ColorEditLastSat;
4770  }
4771  }
4773  {
4774  H = col[0];
4775  S = col[1];
4776  V = col[2];
4777  ColorConvertHSVtoRGB(H, S, V, R, G, B);
4778  }
4779  }
4780 
4781  const int style_alpha8 = IM_F32_TO_INT8_SAT(style.Alpha);
4782  const ImU32 col_black = IM_COL32(0,0,0,style_alpha8);
4783  const ImU32 col_white = IM_COL32(255,255,255,style_alpha8);
4784  const ImU32 col_midgrey = IM_COL32(128,128,128,style_alpha8);
4785  const ImU32 col_hues[6 + 1] = { IM_COL32(255,0,0,style_alpha8), IM_COL32(255,255,0,style_alpha8), IM_COL32(0,255,0,style_alpha8), IM_COL32(0,255,255,style_alpha8), IM_COL32(0,0,255,style_alpha8), IM_COL32(255,0,255,style_alpha8), IM_COL32(255,0,0,style_alpha8) };
4786 
4787  ImVec4 hue_color_f(1, 1, 1, style.Alpha); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
4788  ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
4789  ImU32 user_col32_striped_of_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, style.Alpha)); // Important: this is still including the main rendering/style alpha!!
4790 
4791  ImVec2 sv_cursor_pos;
4792 
4794  {
4795  // Render Hue Wheel
4796  const float aeps = 0.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).
4797  const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12);
4798  for (int n = 0; n < 6; n++)
4799  {
4800  const float a0 = (n) /6.0f * 2.0f * IM_PI - aeps;
4801  const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
4802  const int vert_start_idx = draw_list->VtxBuffer.Size;
4803  draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
4804  draw_list->PathStroke(col_white, false, wheel_thickness);
4805  const int vert_end_idx = draw_list->VtxBuffer.Size;
4806 
4807  // Paint colors over existing vertices
4808  ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner);
4809  ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner);
4810  ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n+1]);
4811  }
4812 
4813  // Render Cursor + preview on Hue Wheel
4814  float cos_hue_angle = ImCos(H * 2.0f * IM_PI);
4815  float sin_hue_angle = ImSin(H * 2.0f * IM_PI);
4816  ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f);
4817  float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
4818  int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);
4819  draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
4820  draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, col_midgrey, hue_cursor_segments);
4821  draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
4822 
4823  // Render SV triangle (rotated according to hue)
4824  ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
4825  ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
4826  ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
4827  ImVec2 uv_white = GetFontTexUvWhitePixel();
4828  draw_list->PrimReserve(6, 6);
4829  draw_list->PrimVtx(tra, uv_white, hue_color32);
4830  draw_list->PrimVtx(trb, uv_white, hue_color32);
4831  draw_list->PrimVtx(trc, uv_white, col_white);
4832  draw_list->PrimVtx(tra, uv_white, 0);
4833  draw_list->PrimVtx(trb, uv_white, col_black);
4834  draw_list->PrimVtx(trc, uv_white, 0);
4835  draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f);
4836  sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
4837  }
4839  {
4840  // Render SV Square
4841  draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white);
4842  draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black);
4843  RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f);
4844  sv_cursor_pos.x = ImClamp(IM_ROUND(picker_pos.x + ImSaturate(S) * sv_picker_size), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much
4845  sv_cursor_pos.y = ImClamp(IM_ROUND(picker_pos.y + ImSaturate(1 - V) * sv_picker_size), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2);
4846 
4847  // Render Hue Bar
4848  for (int i = 0; i < 6; ++i)
4849  draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]);
4850  float bar0_line_y = IM_ROUND(picker_pos.y + H * sv_picker_size);
4851  RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);
4852  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, style.Alpha);
4853  }
4854 
4855  // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
4856  float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
4857  draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12);
4858  draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, col_midgrey, 12);
4859  draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12);
4860 
4861  // Render alpha bar
4862  if (alpha_bar)
4863  {
4864  float alpha = ImSaturate(col[3]);
4865  ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
4866  RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
4867  draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK);
4868  float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size);
4869  RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
4870  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, style.Alpha);
4871  }
4872 
4873  EndGroup();
4874 
4875  if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0)
4876  value_changed = false;
4877  if (value_changed)
4878  MarkItemEdited(window->DC.LastItemId);
4879 
4880  PopID();
4881 
4882  return value_changed;
4883 }
4884 
4885 // A little colored square. Return true when clicked.
4886 // FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip.
4887 // 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip.
4888 // Note that 'col' may be encoded in HSV if ImGuiColorEditFlags_InputHSV is set.
4889 bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, ImVec2 size)
4890 {
4891  ImGuiWindow* window = GetCurrentWindow();
4892  if (window->SkipItems)
4893  return false;
4894 
4895  ImGuiContext& g = *GImGui;
4896  const ImGuiID id = window->GetID(desc_id);
4897  float default_size = GetFrameHeight();
4898  if (size.x == 0.0f)
4899  size.x = default_size;
4900  if (size.y == 0.0f)
4901  size.y = default_size;
4902  const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
4903  ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f);
4904  if (!ItemAdd(bb, id))
4905  return false;
4906 
4907  bool hovered, held;
4908  bool pressed = ButtonBehavior(bb, id, &hovered, &held);
4909 
4912 
4913  ImVec4 col_rgb = col;
4915  ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z);
4916 
4917  ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f);
4918  float grid_step = ImMin(size.x, size.y) / 2.99f;
4919  float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
4920  ImRect bb_inner = bb;
4921  float off = 0.0f;
4922  if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
4923  {
4924  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.
4925  bb_inner.Expand(off);
4926  }
4927  if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
4928  {
4929  float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f);
4930  RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight);
4931  window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft);
4932  }
4933  else
4934  {
4935  // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha
4936  ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col_rgb : col_rgb_without_alpha;
4937  if (col_source.w < 1.0f)
4938  RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding);
4939  else
4940  window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding, ImDrawCornerFlags_All);
4941  }
4942  RenderNavHighlight(bb, id);
4943  if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
4944  {
4945  if (g.Style.FrameBorderSize > 0.0f)
4946  RenderFrameBorder(bb.Min, bb.Max, rounding);
4947  else
4948  window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border
4949  }
4950 
4951  // Drag and Drop Source
4952  // NB: The ActiveId test is merely an optional micro-optimization, BeginDragDropSource() does the same test.
4953  if (g.ActiveId == id && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropSource())
4954  {
4956  SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once);
4957  else
4958  SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once);
4959  ColorButton(desc_id, col, flags);
4960  SameLine();
4961  TextEx("Color");
4963  }
4964 
4965  // Tooltip
4966  if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered)
4968 
4969  return pressed;
4970 }
4971 
4972 // Initialize/override default color options
4974 {
4975  ImGuiContext& g = *GImGui;
4984  IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DisplayMask)); // Check only 1 option is selected
4985  IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__DataTypeMask)); // Check only 1 option is selected
4986  IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__PickerMask)); // Check only 1 option is selected
4987  IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags__InputMask)); // Check only 1 option is selected
4988  g.ColorEditOptions = flags;
4989 }
4990 
4991 // Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
4992 void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags)
4993 {
4994  ImGuiContext& g = *GImGui;
4995 
4997  const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
4998  if (text_end > text)
4999  {
5000  TextEx(text, text_end);
5001  Separator();
5002  }
5003 
5004  ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2);
5005  ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
5006  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]);
5008  SameLine();
5010  {
5012  Text("#%02X%02X%02X\nR: %d, G: %d, B: %d\n(%.3f, %.3f, %.3f)", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]);
5013  else
5014  Text("#%02X%02X%02X%02X\nR:%d, G:%d, B:%d, A:%d\n(%.3f, %.3f, %.3f, %.3f)", cr, cg, cb, ca, cr, cg, cb, ca, col[0], col[1], col[2], col[3]);
5015  }
5017  {
5019  Text("H: %.3f, S: %.3f, V: %.3f", col[0], col[1], col[2]);
5020  else
5021  Text("H: %.3f, S: %.3f, V: %.3f, A: %.3f", col[0], col[1], col[2], col[3]);
5022  }
5023  EndTooltip();
5024 }
5025 
5027 {
5028  bool allow_opt_inputs = !(flags & ImGuiColorEditFlags__DisplayMask);
5029  bool allow_opt_datatype = !(flags & ImGuiColorEditFlags__DataTypeMask);
5030  if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context"))
5031  return;
5032  ImGuiContext& g = *GImGui;
5034  if (allow_opt_inputs)
5035  {
5039  }
5040  if (allow_opt_datatype)
5041  {
5042  if (allow_opt_inputs) Separator();
5044  if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Float;
5045  }
5046 
5047  if (allow_opt_inputs || allow_opt_datatype)
5048  Separator();
5049  if (Button("Copy as..", ImVec2(-1,0)))
5050  OpenPopup("Copy");
5051  if (BeginPopup("Copy"))
5052  {
5053  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]);
5054  char buf[64];
5055  ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
5056  if (Selectable(buf))
5058  ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca);
5059  if (Selectable(buf))
5061  ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", cr, cg, cb);
5062  if (Selectable(buf))
5065  {
5066  ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", cr, cg, cb, ca);
5067  if (Selectable(buf))
5069  }
5070  EndPopup();
5071  }
5072 
5073  g.ColorEditOptions = opts;
5074  EndPopup();
5075 }
5076 
5078 {
5079  bool allow_opt_picker = !(flags & ImGuiColorEditFlags__PickerMask);
5080  bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar);
5081  if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context"))
5082  return;
5083  ImGuiContext& g = *GImGui;
5084  if (allow_opt_picker)
5085  {
5086  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
5087  PushItemWidth(picker_size.x);
5088  for (int picker_type = 0; picker_type < 2; picker_type++)
5089  {
5090  // Draw small/thumbnail version of each picker type (over an invisible button for selection)
5091  if (picker_type > 0) Separator();
5092  PushID(picker_type);
5094  if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar;
5095  if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;
5096  ImVec2 backup_pos = GetCursorScreenPos();
5097  if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup
5098  g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags__PickerMask) | (picker_flags & ImGuiColorEditFlags__PickerMask);
5099  SetCursorScreenPos(backup_pos);
5100  ImVec4 dummy_ref_col;
5101  memcpy(&dummy_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4));
5102  ColorPicker4("##dummypicker", &dummy_ref_col.x, picker_flags);
5103  PopID();
5104  }
5105  PopItemWidth();
5106  }
5107  if (allow_opt_alpha_bar)
5108  {
5109  if (allow_opt_picker) Separator();
5110  CheckboxFlags("Alpha Bar", (unsigned int*)&g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
5111  }
5112  EndPopup();
5113 }
5114 
5115 //-------------------------------------------------------------------------
5116 // [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
5117 //-------------------------------------------------------------------------
5118 // - TreeNode()
5119 // - TreeNodeV()
5120 // - TreeNodeEx()
5121 // - TreeNodeExV()
5122 // - TreeNodeBehavior() [Internal]
5123 // - TreePush()
5124 // - TreePop()
5125 // - GetTreeNodeToLabelSpacing()
5126 // - SetNextItemOpen()
5127 // - CollapsingHeader()
5128 //-------------------------------------------------------------------------
5129 
5130 bool ImGui::TreeNode(const char* str_id, const char* fmt, ...)
5131 {
5132  va_list args;
5133  va_start(args, fmt);
5134  bool is_open = TreeNodeExV(str_id, 0, fmt, args);
5135  va_end(args);
5136  return is_open;
5137 }
5138 
5139 bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...)
5140 {
5141  va_list args;
5142  va_start(args, fmt);
5143  bool is_open = TreeNodeExV(ptr_id, 0, fmt, args);
5144  va_end(args);
5145  return is_open;
5146 }
5147 
5148 bool ImGui::TreeNode(const char* label)
5149 {
5150  ImGuiWindow* window = GetCurrentWindow();
5151  if (window->SkipItems)
5152  return false;
5153  return TreeNodeBehavior(window->GetID(label), 0, label, NULL);
5154 }
5155 
5156 bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args)
5157 {
5158  return TreeNodeExV(str_id, 0, fmt, args);
5159 }
5160 
5161 bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args)
5162 {
5163  return TreeNodeExV(ptr_id, 0, fmt, args);
5164 }
5165 
5167 {
5168  ImGuiWindow* window = GetCurrentWindow();
5169  if (window->SkipItems)
5170  return false;
5171 
5172  return TreeNodeBehavior(window->GetID(label), flags, label, NULL);
5173 }
5174 
5175 bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
5176 {
5177  va_list args;
5178  va_start(args, fmt);
5179  bool is_open = TreeNodeExV(str_id, flags, fmt, args);
5180  va_end(args);
5181  return is_open;
5182 }
5183 
5184 bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
5185 {
5186  va_list args;
5187  va_start(args, fmt);
5188  bool is_open = TreeNodeExV(ptr_id, flags, fmt, args);
5189  va_end(args);
5190  return is_open;
5191 }
5192 
5193 bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
5194 {
5195  ImGuiWindow* window = GetCurrentWindow();
5196  if (window->SkipItems)
5197  return false;
5198 
5199  ImGuiContext& g = *GImGui;
5200  const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
5201  return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end);
5202 }
5203 
5204 bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
5205 {
5206  ImGuiWindow* window = GetCurrentWindow();
5207  if (window->SkipItems)
5208  return false;
5209 
5210  ImGuiContext& g = *GImGui;
5211  const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
5212  return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end);
5213 }
5214 
5216 {
5218  return true;
5219 
5220  // We only write to the tree storage if the user clicks (or explicitly use the SetNextItemOpen function)
5221  ImGuiContext& g = *GImGui;
5222  ImGuiWindow* window = g.CurrentWindow;
5223  ImGuiStorage* storage = window->DC.StateStorage;
5224 
5225  bool is_open;
5226  if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasOpen)
5227  {
5228  if (g.NextItemData.OpenCond & ImGuiCond_Always)
5229  {
5230  is_open = g.NextItemData.OpenVal;
5231  storage->SetInt(id, is_open);
5232  }
5233  else
5234  {
5235  // We treat ImGuiCond_Once and ImGuiCond_FirstUseEver the same because tree node state are not saved persistently.
5236  const int stored_value = storage->GetInt(id, -1);
5237  if (stored_value == -1)
5238  {
5239  is_open = g.NextItemData.OpenVal;
5240  storage->SetInt(id, is_open);
5241  }
5242  else
5243  {
5244  is_open = stored_value != 0;
5245  }
5246  }
5247  }
5248  else
5249  {
5250  is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0;
5251  }
5252 
5253  // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior).
5254  // NB- If we are above max depth we still allow manually opened nodes to be logged.
5255  if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && (window->DC.TreeDepth - g.LogDepthRef) < g.LogDepthToExpand)
5256  is_open = true;
5257 
5258  return is_open;
5259 }
5260 
5261 bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)
5262 {
5263  ImGuiWindow* window = GetCurrentWindow();
5264  if (window->SkipItems)
5265  return false;
5266 
5267  ImGuiContext& g = *GImGui;
5268  const ImGuiStyle& style = g.Style;
5269  const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0;
5270  const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, ImMin(window->DC.CurrLineTextBaseOffset, style.FramePadding.y));
5271 
5272  if (!label_end)
5273  label_end = FindRenderedTextEnd(label);
5274  const ImVec2 label_size = CalcTextSize(label, label_end, false);
5275 
5276  // We vertically grow up to current line height up the typical widget height.
5277  const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
5278  ImRect frame_bb;
5279  frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x;
5280  frame_bb.Min.y = window->DC.CursorPos.y;
5281  frame_bb.Max.x = window->WorkRect.Max.x;
5282  frame_bb.Max.y = window->DC.CursorPos.y + frame_height;
5283  if (display_frame)
5284  {
5285  // Framed header expand a little outside the default padding, to the edge of InnerClipRect
5286  // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f)
5287  frame_bb.Min.x -= IM_FLOOR(window->WindowPadding.x * 0.5f - 1.0f);
5288  frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f);
5289  }
5290 
5291  const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing
5292  const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
5293  const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
5294  ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
5295  ItemSize(ImVec2(text_width, frame_height), padding.y);
5296 
5297  // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
5298  ImRect interact_bb = frame_bb;
5300  interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f;
5301 
5302  // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child.
5303  // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
5304  // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
5305  const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
5306  bool is_open = TreeNodeBehaviorIsOpen(id, flags);
5307  if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
5308  window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth);
5309 
5310  bool item_add = ItemAdd(interact_bb, id);
5312  window->DC.LastItemDisplayRect = frame_bb;
5313 
5314  if (!item_add)
5315  {
5316  if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
5317  TreePushOverrideID(id);
5318  IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
5319  return is_open;
5320  }
5321 
5324  button_flags |= ImGuiButtonFlags_AllowItemOverlap;
5325  if (!is_leaf)
5327 
5328  // We allow clicking on the arrow section with keyboard modifiers held, in order to easily
5329  // allow browsing a tree while preserving selection with code implementing multi-selection patterns.
5330  // When clicking on the rest of the tree node we always disallow keyboard modifiers.
5331  const float arrow_hit_x1 = (text_pos.x - text_offset_x) - style.TouchExtraPadding.x;
5332  const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x;
5333  const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2);
5334  if (window != g.HoveredWindow || !is_mouse_x_over_arrow)
5335  button_flags |= ImGuiButtonFlags_NoKeyModifiers;
5336 
5337  // Open behaviors can be altered with the _OpenOnArrow and _OnOnDoubleClick flags.
5338  // Some alteration have subtle effects (e.g. toggle on MouseUp vs MouseDown events) due to requirements for multi-selection and drag and drop support.
5339  // - Single-click on label = Toggle on MouseUp (default)
5340  // - Single-click on arrow = Toggle on MouseUp (when _OpenOnArrow=0)
5341  // - Single-click on arrow = Toggle on MouseDown (when _OpenOnArrow=1)
5342  // - Double-click on label = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1)
5343  // - Double-click on arrow = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1 and _OpenOnArrow=0)
5344  // This makes _OpenOnArrow have a subtle effect on _OpenOnDoubleClick: arrow click reacts on Down rather than Up.
5345  // It is rather standard that arrow click react on Down rather than Up and we'd be tempted to make it the default
5346  // (by removing the _OpenOnArrow test below), however this would have a perhaps surprising effect on CollapsingHeader()?
5347  // So right now we are making this optional. May evolve later.
5348  if (is_mouse_x_over_arrow && (flags & ImGuiTreeNodeFlags_OpenOnArrow))
5349  button_flags |= ImGuiButtonFlags_PressedOnClick;
5351  button_flags |= ImGuiButtonFlags_PressedOnDoubleClick;
5352  else
5354 
5355  bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
5356  const bool was_selected = selected;
5357 
5358  bool hovered, held;
5359  bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags);
5360  bool toggled = false;
5361  if (!is_leaf)
5362  {
5363  if (pressed)
5364  {
5365  if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id))
5366  toggled = true;
5368  toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
5369  if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseDoubleClicked[0])
5370  toggled = true;
5371  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.
5372  toggled = false;
5373  }
5374 
5375  if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Left && is_open)
5376  {
5377  toggled = true;
5379  }
5380  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?
5381  {
5382  toggled = true;
5384  }
5385 
5386  if (toggled)
5387  {
5388  is_open = !is_open;
5389  window->DC.StateStorage->SetInt(id, is_open);
5391  }
5392  }
5395 
5396  // In this branch, TreeNodeBehavior() cannot toggle the selection so this will never trigger.
5397  if (selected != was_selected) //-V547
5399 
5400  // Render
5401  const ImU32 text_col = GetColorU32(ImGuiCol_Text);
5403  if (display_frame)
5404  {
5405  // Framed type
5406  const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
5407  RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
5408  RenderNavHighlight(frame_bb, id, nav_highlight_flags);
5410  RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
5411  else if (!is_leaf)
5412  RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
5413  else // Leaf without bullet, left-adjusted text
5414  text_pos.x -= text_offset_x;
5416  frame_bb.Max.x -= g.FontSize + style.FramePadding.x;
5417  if (g.LogEnabled)
5418  {
5419  // 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.
5420  const char log_prefix[] = "\n##";
5421  const char log_suffix[] = "##";
5422  LogRenderedText(&text_pos, log_prefix, log_prefix+3);
5423  RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
5424  LogRenderedText(&text_pos, log_suffix, log_suffix+2);
5425  }
5426  else
5427  {
5428  RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
5429  }
5430  }
5431  else
5432  {
5433  // Unframed typed for tree nodes
5434  if (hovered || selected)
5435  {
5436  const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
5437  RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
5438  RenderNavHighlight(frame_bb, id, nav_highlight_flags);
5439  }
5441  RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
5442  else if (!is_leaf)
5443  RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
5444  if (g.LogEnabled)
5445  LogRenderedText(&text_pos, ">");
5446  RenderText(text_pos, label, label_end, false);
5447  }
5448 
5449  if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
5450  TreePushOverrideID(id);
5451  IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
5452  return is_open;
5453 }
5454 
5455 void ImGui::TreePush(const char* str_id)
5456 {
5457  ImGuiWindow* window = GetCurrentWindow();
5458  Indent();
5459  window->DC.TreeDepth++;
5460  PushID(str_id ? str_id : "#TreePush");
5461 }
5462 
5463 void ImGui::TreePush(const void* ptr_id)
5464 {
5465  ImGuiWindow* window = GetCurrentWindow();
5466  Indent();
5467  window->DC.TreeDepth++;
5468  PushID(ptr_id ? ptr_id : (const void*)"#TreePush");
5469 }
5470 
5472 {
5473  ImGuiWindow* window = GetCurrentWindow();
5474  Indent();
5475  window->DC.TreeDepth++;
5476  window->IDStack.push_back(id);
5477 }
5478 
5480 {
5481  ImGuiContext& g = *GImGui;
5482  ImGuiWindow* window = g.CurrentWindow;
5483  Unindent();
5484 
5485  window->DC.TreeDepth--;
5486  ImU32 tree_depth_mask = (1 << window->DC.TreeDepth);
5487 
5488  // Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled)
5489  if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
5490  if (g.NavIdIsAlive && (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask))
5491  {
5492  SetNavID(window->IDStack.back(), g.NavLayer, 0);
5494  }
5495  window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1;
5496 
5497  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.
5498  PopID();
5499 }
5500 
5501 // Horizontal distance preceding label when using TreeNode() or Bullet()
5503 {
5504  ImGuiContext& g = *GImGui;
5505  return g.FontSize + (g.Style.FramePadding.x * 2.0f);
5506 }
5507 
5508 // Set next TreeNode/CollapsingHeader open state.
5509 void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond)
5510 {
5511  ImGuiContext& g = *GImGui;
5512  if (g.CurrentWindow->SkipItems)
5513  return;
5515  g.NextItemData.OpenVal = is_open;
5516  g.NextItemData.OpenCond = cond ? cond : ImGuiCond_Always;
5517 }
5518 
5519 // CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag).
5520 // 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().
5522 {
5523  ImGuiWindow* window = GetCurrentWindow();
5524  if (window->SkipItems)
5525  return false;
5526 
5528 }
5529 
5530 bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags)
5531 {
5532  ImGuiWindow* window = GetCurrentWindow();
5533  if (window->SkipItems)
5534  return false;
5535 
5536  if (p_open && !*p_open)
5537  return false;
5538 
5539  ImGuiID id = window->GetID(label);
5541  if (p_open)
5543  bool is_open = TreeNodeBehavior(id, flags, label);
5544  if (p_open)
5545  {
5546  // Create a small overlapping close button
5547  // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc.
5548  // FIXME: CloseButton can overlap into text, need find a way to clip the text somehow.
5549  ImGuiContext& g = *GImGui;
5550  ImGuiItemHoveredDataBackup last_item_backup;
5551  float button_size = g.FontSize;
5552  float button_x = ImMax(window->DC.LastItemRect.Min.x, window->DC.LastItemRect.Max.x - g.Style.FramePadding.x * 2.0f - button_size);
5553  float button_y = window->DC.LastItemRect.Min.y;
5554  if (CloseButton(window->GetID((void*)((intptr_t)id + 1)), ImVec2(button_x, button_y)))
5555  *p_open = false;
5556  last_item_backup.Restore();
5557  }
5558 
5559  return is_open;
5560 }
5561 
5562 //-------------------------------------------------------------------------
5563 // [SECTION] Widgets: Selectable
5564 //-------------------------------------------------------------------------
5565 // - Selectable()
5566 //-------------------------------------------------------------------------
5567 
5568 // Tip: pass a non-visible label (e.g. "##dummy") then you can use the space to draw other text or image.
5569 // But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id.
5570 // With this scheme, ImGuiSelectableFlags_SpanAllColumns and ImGuiSelectableFlags_AllowItemOverlap are also frequently used flags.
5571 // FIXME: Selectable() with (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported.
5572 bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
5573 {
5574  ImGuiWindow* window = GetCurrentWindow();
5575  if (window->SkipItems)
5576  return false;
5577 
5578  ImGuiContext& g = *GImGui;
5579  const ImGuiStyle& style = g.Style;
5580 
5581  if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped.
5583 
5584  // Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle.
5585  ImGuiID id = window->GetID(label);
5586  ImVec2 label_size = CalcTextSize(label, NULL, true);
5587  ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
5588  ImVec2 pos = window->DC.CursorPos;
5589  pos.y += window->DC.CurrLineTextBaseOffset;
5590  ItemSize(size, 0.0f);
5591 
5592  // Fill horizontal space
5593  const float min_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Min.x : pos.x;
5595  if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth))
5596  size.x = ImMax(label_size.x, max_x - min_x);
5597 
5598  // Text stays at the submission position, but bounding box may be extended on both sides
5599  const ImVec2 text_min = pos;
5600  const ImVec2 text_max(min_x + size.x, pos.y + size.y);
5601 
5602  // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
5603  ImRect bb_enlarged(min_x, pos.y, text_max.x, text_max.y);
5604  const float spacing_x = style.ItemSpacing.x;
5605  const float spacing_y = style.ItemSpacing.y;
5606  const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
5607  const float spacing_U = IM_FLOOR(spacing_y * 0.50f);
5608  bb_enlarged.Min.x -= spacing_L;
5609  bb_enlarged.Min.y -= spacing_U;
5610  bb_enlarged.Max.x += (spacing_x - spacing_L);
5611  bb_enlarged.Max.y += (spacing_y - spacing_U);
5612  //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_align.Min, bb_align.Max, IM_COL32(255, 0, 0, 255)); }
5613  //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_enlarged.Min, bb_enlarged.Max, IM_COL32(0, 255, 0, 255)); }
5614 
5615  bool item_add;
5617  {
5618  ImGuiItemFlags backup_item_flags = window->DC.ItemFlags;
5620  item_add = ItemAdd(bb_enlarged, id);
5621  window->DC.ItemFlags = backup_item_flags;
5622  }
5623  else
5624  {
5625  item_add = ItemAdd(bb_enlarged, id);
5626  }
5627  if (!item_add)
5628  {
5631  return false;
5632  }
5633 
5634  // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries
5635  ImGuiButtonFlags button_flags = 0;
5642 
5644  selected = false;
5645 
5646  const bool was_selected = selected;
5647  bool hovered, held;
5648  bool pressed = ButtonBehavior(bb_enlarged, id, &hovered, &held, button_flags);
5649 
5650  // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
5651  if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
5652  {
5653  if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
5654  {
5655  g.NavDisableHighlight = true;
5656  SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent);
5657  }
5658  }
5659  if (pressed)
5660  MarkItemEdited(id);
5661 
5664 
5665  // In this branch, Selectable() cannot toggle the selection so this will never trigger.
5666  if (selected != was_selected) //-V547
5668 
5669  // Render
5671  hovered = true;
5672  if (hovered || selected)
5673  {
5674  const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
5675  RenderFrame(bb_enlarged.Min, bb_enlarged.Max, col, false, 0.0f);
5677  }
5678 
5681 
5683  RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb_enlarged);
5685 
5686  // Automatically close popups
5689 
5691  return pressed;
5692 }
5693 
5694 bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
5695 {
5696  if (Selectable(label, *p_selected, flags, size_arg))
5697  {
5698  *p_selected = !*p_selected;
5699  return true;
5700  }
5701  return false;
5702 }
5703 
5704 //-------------------------------------------------------------------------
5705 // [SECTION] Widgets: ListBox
5706 //-------------------------------------------------------------------------
5707 // - ListBox()
5708 // - ListBoxHeader()
5709 // - ListBoxFooter()
5710 //-------------------------------------------------------------------------
5711 // FIXME: This is an old API. We should redesign some of it, rename ListBoxHeader->BeginListBox, ListBoxFooter->EndListBox
5712 // and promote using them over existing ListBox() functions, similarly to change with combo boxes.
5713 //-------------------------------------------------------------------------
5714 
5715 // FIXME: In principle this function should be called BeginListBox(). We should rename it after re-evaluating if we want to keep the same signature.
5716 // Helper to calculate the size of a listbox and display a label on the right.
5717 // Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an non-visible label e.g. "##empty"
5718 bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
5719 {
5720  ImGuiContext& g = *GImGui;
5721  ImGuiWindow* window = GetCurrentWindow();
5722  if (window->SkipItems)
5723  return false;
5724 
5725  const ImGuiStyle& style = g.Style;
5726  const ImGuiID id = GetID(label);
5727  const ImVec2 label_size = CalcTextSize(label, NULL, true);
5728 
5729  // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
5731  ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
5732  ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
5733  ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
5734  window->DC.LastItemRect = bb; // Forward storage for ListBoxFooter.. dodgy.
5735  g.NextItemData.ClearFlags();
5736 
5737  if (!IsRectVisible(bb.Min, bb.Max))
5738  {
5739  ItemSize(bb.GetSize(), style.FramePadding.y);
5740  ItemAdd(bb, 0, &frame_bb);
5741  return false;
5742  }
5743 
5744  BeginGroup();
5745  if (label_size.x > 0)
5746  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
5747 
5748  BeginChildFrame(id, frame_bb.GetSize());
5749  return true;
5750 }
5751 
5752 // FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature.
5753 bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
5754 {
5755  // Size default to hold ~7.25 items.
5756  // 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.
5757  // 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.
5758  // I am expecting that someone will come and complain about this behavior in a remote future, then we can advise on a better solution.
5759  if (height_in_items < 0)
5760  height_in_items = ImMin(items_count, 7);
5761  const ImGuiStyle& style = GetStyle();
5762  float height_in_items_f = (height_in_items < items_count) ? (height_in_items + 0.25f) : (height_in_items + 0.00f);
5763 
5764  // 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().
5765  ImVec2 size;
5766  size.x = 0.0f;
5767  size.y = ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f);
5768  return ListBoxHeader(label, size);
5769 }
5770 
5771 // FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature.
5773 {
5774  ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow;
5775  const ImRect bb = parent_window->DC.LastItemRect;
5776  const ImGuiStyle& style = GetStyle();
5777 
5778  EndChildFrame();
5779 
5780  // Redeclare item size so that it includes the label (we have stored the full size in LastItemRect)
5781  // We call SameLine() to restore DC.CurrentLine* data
5782  SameLine();
5783  parent_window->DC.CursorPos = bb.Min;
5784  ItemSize(bb, style.FramePadding.y);
5785  EndGroup();
5786 }
5787 
5788 bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items)
5789 {
5790  const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items);
5791  return value_changed;
5792 }
5793 
5794 bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)
5795 {
5796  if (!ListBoxHeader(label, items_count, height_in_items))
5797  return false;
5798 
5799  // 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.
5800  ImGuiContext& g = *GImGui;
5801  bool value_changed = false;
5802  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.
5803  while (clipper.Step())
5804  for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
5805  {
5806  const bool item_selected = (i == *current_item);
5807  const char* item_text;
5808  if (!items_getter(data, i, &item_text))
5809  item_text = "*Unknown item*";
5810 
5811  PushID(i);
5812  if (Selectable(item_text, item_selected))
5813  {
5814  *current_item = i;
5815  value_changed = true;
5816  }
5817  if (item_selected)
5819  PopID();
5820  }
5821  ListBoxFooter();
5822  if (value_changed)
5823  MarkItemEdited(g.CurrentWindow->DC.LastItemId);
5824 
5825  return value_changed;
5826 }
5827 
5828 //-------------------------------------------------------------------------
5829 // [SECTION] Widgets: PlotLines, PlotHistogram
5830 //-------------------------------------------------------------------------
5831 // - PlotEx() [Internal]
5832 // - PlotLines()
5833 // - PlotHistogram()
5834 //-------------------------------------------------------------------------
5835 
5836 void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size)
5837 {
5838  ImGuiWindow* window = GetCurrentWindow();
5839  if (window->SkipItems)
5840  return;
5841 
5842  ImGuiContext& g = *GImGui;
5843  const ImGuiStyle& style = g.Style;
5844  const ImGuiID id = window->GetID(label);
5845 
5846  const ImVec2 label_size = CalcTextSize(label, NULL, true);
5847  if (frame_size.x == 0.0f)
5848  frame_size.x = CalcItemWidth();
5849  if (frame_size.y == 0.0f)
5850  frame_size.y = label_size.y + (style.FramePadding.y * 2);
5851 
5852  const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
5853  const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
5854  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));
5855  ItemSize(total_bb, style.FramePadding.y);
5856  if (!ItemAdd(total_bb, 0, &frame_bb))
5857  return;
5858  const bool hovered = ItemHoverable(frame_bb, id);
5859 
5860  // Determine scale from values if not specified
5861  if (scale_min == FLT_MAX || scale_max == FLT_MAX)
5862  {
5863  float v_min = FLT_MAX;
5864  float v_max = -FLT_MAX;
5865  for (int i = 0; i < values_count; i++)
5866  {
5867  const float v = values_getter(data, i);
5868  if (v != v) // Ignore NaN values
5869  continue;
5870  v_min = ImMin(v_min, v);
5871  v_max = ImMax(v_max, v);
5872  }
5873  if (scale_min == FLT_MAX)
5874  scale_min = v_min;
5875  if (scale_max == FLT_MAX)
5876  scale_max = v_max;
5877  }
5878 
5879  RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
5880 
5881  const int values_count_min = (plot_type == ImGuiPlotType_Lines) ? 2 : 1;
5882  if (values_count >= values_count_min)
5883  {
5884  int res_w = ImMin((int)frame_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
5885  int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
5886 
5887  // Tooltip on hover
5888  int v_hovered = -1;
5889  if (hovered && inner_bb.Contains(g.IO.MousePos))
5890  {
5891  const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
5892  const int v_idx = (int)(t * item_count);
5893  IM_ASSERT(v_idx >= 0 && v_idx < values_count);
5894 
5895  const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
5896  const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);
5897  if (plot_type == ImGuiPlotType_Lines)
5898  SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1);
5899  else if (plot_type == ImGuiPlotType_Histogram)
5900  SetTooltip("%d: %8.4g", v_idx, v0);
5901  v_hovered = v_idx;
5902  }
5903 
5904  const float t_step = 1.0f / (float)res_w;
5905  const float inv_scale = (scale_min == scale_max) ? 0.0f : (1.0f / (scale_max - scale_min));
5906 
5907  float v0 = values_getter(data, (0 + values_offset) % values_count);
5908  float t0 = 0.0f;
5909  ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle
5910  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
5911 
5912  const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
5914 
5915  for (int n = 0; n < res_w; n++)
5916  {
5917  const float t1 = t0 + t_step;
5918  const int v1_idx = (int)(t0 * item_count + 0.5f);
5919  IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
5920  const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
5921  const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) );
5922 
5923  // 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.
5924  ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
5925  ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t));
5926  if (plot_type == ImGuiPlotType_Lines)
5927  {
5928  window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
5929  }
5930  else if (plot_type == ImGuiPlotType_Histogram)
5931  {
5932  if (pos1.x >= pos0.x + 2.0f)
5933  pos1.x -= 1.0f;
5934  window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
5935  }
5936 
5937  t0 = t1;
5938  tp0 = tp1;
5939  }
5940  }
5941 
5942  // Text overlay
5943  if (overlay_text)
5944  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));
5945 
5946  if (label_size.x > 0.0f)
5947  RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
5948 }
5949 
5951 {
5952  const float* Values;
5953  int Stride;
5954 
5956 };
5957 
5958 static float Plot_ArrayGetter(void* data, int idx)
5959 {
5961  const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride);
5962  return v;
5963 }
5964 
5965 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)
5966 {
5968  PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5969 }
5970 
5971 void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
5972 {
5973  PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5974 }
5975 
5976 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)
5977 {
5979  PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5980 }
5981 
5982 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)
5983 {
5984  PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
5985 }
5986 
5987 //-------------------------------------------------------------------------
5988 // [SECTION] Widgets: Value helpers
5989 // Those is not very useful, legacy API.
5990 //-------------------------------------------------------------------------
5991 // - Value()
5992 //-------------------------------------------------------------------------
5993 
5994 void ImGui::Value(const char* prefix, bool b)
5995 {
5996  Text("%s: %s", prefix, (b ? "true" : "false"));
5997 }
5998 
5999 void ImGui::Value(const char* prefix, int v)
6000 {
6001  Text("%s: %d", prefix, v);
6002 }
6003 
6004 void ImGui::Value(const char* prefix, unsigned int v)
6005 {
6006  Text("%s: %d", prefix, v);
6007 }
6008 
6009 void ImGui::Value(const char* prefix, float v, const char* float_format)
6010 {
6011  if (float_format)
6012  {
6013  char fmt[64];
6014  ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format);
6015  Text(fmt, prefix, v);
6016  }
6017  else
6018  {
6019  Text("%s: %.3f", prefix, v);
6020  }
6021 }
6022 
6023 //-------------------------------------------------------------------------
6024 // [SECTION] MenuItem, BeginMenu, EndMenu, etc.
6025 //-------------------------------------------------------------------------
6026 // - ImGuiMenuColumns [Internal]
6027 // - BeginMenuBar()
6028 // - EndMenuBar()
6029 // - BeginMainMenuBar()
6030 // - EndMainMenuBar()
6031 // - BeginMenu()
6032 // - EndMenu()
6033 // - MenuItem()
6034 //-------------------------------------------------------------------------
6035 
6036 // Helpers for internal use
6038 {
6039  Spacing = Width = NextWidth = 0.0f;
6040  memset(Pos, 0, sizeof(Pos));
6041  memset(NextWidths, 0, sizeof(NextWidths));
6042 }
6043 
6044 void ImGuiMenuColumns::Update(int count, float spacing, bool clear)
6045 {
6047  IM_UNUSED(count);
6048  Width = NextWidth = 0.0f;
6049  Spacing = spacing;
6050  if (clear)
6051  memset(NextWidths, 0, sizeof(NextWidths));
6052  for (int i = 0; i < IM_ARRAYSIZE(Pos); i++)
6053  {
6054  if (i > 0 && NextWidths[i] > 0.0f)
6055  Width += Spacing;
6056  Pos[i] = IM_FLOOR(Width);
6057  Width += NextWidths[i];
6058  NextWidths[i] = 0.0f;
6059  }
6060 }
6061 
6062 float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double
6063 {
6064  NextWidth = 0.0f;
6065  NextWidths[0] = ImMax(NextWidths[0], w0);
6066  NextWidths[1] = ImMax(NextWidths[1], w1);
6067  NextWidths[2] = ImMax(NextWidths[2], w2);
6068  for (int i = 0; i < IM_ARRAYSIZE(Pos); i++)
6069  NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f);
6070  return ImMax(Width, NextWidth);
6071 }
6072 
6073 float ImGuiMenuColumns::CalcExtraSpace(float avail_w) const
6074 {
6075  return ImMax(0.0f, avail_w - Width);
6076 }
6077 
6078 // FIXME: Provided a rectangle perhaps e.g. a BeginMenuBarEx() could be used anywhere..
6079 // Currently the main responsibility of this function being to setup clip-rect + horizontal layout + menu navigation layer.
6080 // Ideally we also want this to be responsible for claiming space out of the main window scrolling rectangle, in which case ImGuiWindowFlags_MenuBar will become unnecessary.
6081 // Then later the same system could be used for multiple menu-bars, scrollbars, side-bars.
6083 {
6084  ImGuiWindow* window = GetCurrentWindow();
6085  if (window->SkipItems)
6086  return false;
6087  if (!(window->Flags & ImGuiWindowFlags_MenuBar))
6088  return false;
6089 
6090  IM_ASSERT(!window->DC.MenuBarAppending);
6091  BeginGroup(); // Backup position on layer 0 // FIXME: Misleading to use a group for that backup/restore
6092  PushID("##menubar");
6093 
6094  // 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.
6095  // 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.
6096  ImRect bar_rect = window->MenuBarRect();
6097  ImRect clip_rect(IM_ROUND(bar_rect.Min.x + window->WindowBorderSize), IM_ROUND(bar_rect.Min.y + window->WindowBorderSize), IM_ROUND(ImMax(bar_rect.Min.x, bar_rect.Max.x - ImMax(window->WindowRounding, window->WindowBorderSize))), IM_ROUND(bar_rect.Max.y));
6098  clip_rect.ClipWith(window->OuterRectClipped);
6099  PushClipRect(clip_rect.Min, clip_rect.Max, false);
6100 
6101  window->DC.CursorPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffset.x, bar_rect.Min.y + window->DC.MenuBarOffset.y);
6104  window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
6105  window->DC.MenuBarAppending = true;
6107  return true;
6108 }
6109 
6111 {
6112  ImGuiWindow* window = GetCurrentWindow();
6113  if (window->SkipItems)
6114  return;
6115  ImGuiContext& g = *GImGui;
6116 
6117  // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings.
6118  if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
6119  {
6120  ImGuiWindow* nav_earliest_child = g.NavWindow;
6121  while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu))
6122  nav_earliest_child = nav_earliest_child->ParentWindow;
6123  if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && g.NavMoveRequestForward == ImGuiNavForward_None)
6124  {
6125  // To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
6126  // 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)
6128  IM_ASSERT(window->DC.NavLayerActiveMaskNext & (1 << layer)); // Sanity check
6129  FocusWindow(window);
6130  SetNavIDWithRectRel(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
6131  g.NavLayer = layer;
6132  g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
6133  g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
6135  }
6136  }
6137 
6139  IM_ASSERT(window->DC.MenuBarAppending);
6140  PopClipRect();
6141  PopID();
6142  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.
6143  window->DC.GroupStack.back().EmitItem = false;
6144  EndGroup(); // Restore position on layer 0
6147  window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
6148  window->DC.MenuBarAppending = false;
6149 }
6150 
6151 // For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set.
6153 {
6154  ImGuiContext& g = *GImGui;
6155  g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f));
6156  SetNextWindowPos(ImVec2(0.0f, 0.0f));
6157  SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.NextWindowData.MenuBarOffsetMinVal.y + g.FontBaseSize + g.Style.FramePadding.y));
6161  bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar();
6162  PopStyleVar(2);
6163  g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
6164  if (!is_open)
6165  {
6166  End();
6167  return false;
6168  }
6169  return true; //-V1020
6170 }
6171 
6173 {
6174  EndMenuBar();
6175 
6176  // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window
6177  // FIXME: With this strategy we won't be able to restore a NULL focus.
6178  ImGuiContext& g = *GImGui;
6179  if (g.CurrentWindow == g.NavWindow && g.NavLayer == 0 && !g.NavAnyRequest)
6180  FocusTopMostWindowUnderOne(g.NavWindow, NULL);
6181 
6182  End();
6183 }
6184 
6185 bool ImGui::BeginMenu(const char* label, bool enabled)
6186 {
6187  ImGuiWindow* window = GetCurrentWindow();
6188  if (window->SkipItems)
6189  return false;
6190 
6191  ImGuiContext& g = *GImGui;
6192  const ImGuiStyle& style = g.Style;
6193  const ImGuiID id = window->GetID(label);
6194  bool menu_is_open = IsPopupOpen(id);
6195 
6196  // 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)
6200 
6201  // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin().
6202  // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame.
6203  // If somehow this is ever becoming a problem we can switch to use e.g. a ImGuiStorager mapping key to last frame used.
6204  if (g.MenusIdSubmittedThisFrame.contains(id))
6205  {
6206  if (menu_is_open)
6207  menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
6208  else
6209  g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values
6210  return menu_is_open;
6211  }
6212 
6213  // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu
6214  g.MenusIdSubmittedThisFrame.push_back(id);
6215 
6216  ImVec2 label_size = CalcTextSize(label, NULL, true);
6217  bool pressed;
6218  bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
6219  ImGuiWindow* backed_nav_window = g.NavWindow;
6220  if (menuset_is_open)
6221  g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
6222 
6223  // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
6224  // However the final position is going to be different! It is choosen by FindBestWindowPosForPopup().
6225  // e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering.
6226  ImVec2 popup_pos, pos = window->DC.CursorPos;
6227  if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
6228  {
6229  // Menu inside an horizontal menu bar
6230  // Selectable extend their highlight by half ItemSpacing in each direction.
6231  // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
6232  popup_pos = ImVec2(pos.x - 1.0f - IM_FLOOR(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight());
6233  window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
6235  float w = label_size.x;
6237  PopStyleVar();
6238  window->DC.CursorPos.x += IM_FLOOR(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().
6239  }
6240  else
6241  {
6242  // Menu inside a menu
6243  // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
6244  // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
6245  popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
6246  float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame
6247  float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
6250  RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right);
6251  }
6252 
6253  const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id);
6254  if (menuset_is_open)
6255  g.NavWindow = backed_nav_window;
6256 
6257  bool want_open = false;
6258  bool want_close = false;
6259  if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
6260  {
6261  // Close menu when not hovering it anymore unless we are moving roughly in the direction of the menu
6262  // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.
6263  bool moving_toward_other_child_menu = false;
6264 
6265  ImGuiWindow* child_menu_window = (g.BeginPopupStack.Size < g.OpenPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].SourceWindow == window) ? g.OpenPopupStack[g.BeginPopupStack.Size].Window : NULL;
6266  if (g.HoveredWindow == window && child_menu_window != NULL && !(window->Flags & ImGuiWindowFlags_MenuBar))
6267  {
6268  // FIXME-DPI: Values should be derived from a master "scale" factor.
6269  ImRect next_window_rect = child_menu_window->Rect();
6270  ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta;
6271  ImVec2 tb = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();
6272  ImVec2 tc = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR();
6273  float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack.
6274  ta.x += (window->Pos.x < child_menu_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues
6275  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?
6276  tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f);
6277  moving_toward_other_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
6278  //GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG]
6279  }
6280  if (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_toward_other_child_menu)
6281  want_close = true;
6282 
6283  if (!menu_is_open && hovered && pressed) // Click to open
6284  want_open = true;
6285  else if (!menu_is_open && hovered && !moving_toward_other_child_menu) // Hover to open
6286  want_open = true;
6287 
6288  if (g.NavActivateId == id)
6289  {
6290  want_close = menu_is_open;
6291  want_open = !menu_is_open;
6292  }
6293  if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
6294  {
6295  want_open = true;
6297  }
6298  }
6299  else
6300  {
6301  // Menu bar
6302  if (menu_is_open && pressed && menuset_is_open) // Click an open menu again to close it
6303  {
6304  want_close = true;
6305  want_open = menu_is_open = false;
6306  }
6307  else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // First click to open, then hover to open others
6308  {
6309  want_open = true;
6310  }
6311  else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open
6312  {
6313  want_open = true;
6315  }
6316  }
6317 
6318  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.. }'
6319  want_close = true;
6320  if (want_close && IsPopupOpen(id))
6321  ClosePopupToLevel(g.BeginPopupStack.Size, true);
6322 
6323  IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
6324 
6325  if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
6326  {
6327  // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame.
6328  OpenPopup(label);
6329  return false;
6330  }
6331 
6332  menu_is_open |= want_open;
6333  if (want_open)
6334  OpenPopup(label);
6335 
6336  if (menu_is_open)
6337  {
6338  SetNextWindowPos(popup_pos, ImGuiCond_Always);
6339  menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
6340  }
6341  else
6342  {
6343  g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
6344  }
6345 
6346  return menu_is_open;
6347 }
6348 
6350 {
6351  // Nav: When a left move request _within our child menu_ failed, close ourselves (the _parent_ menu).
6352  // A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs.
6353  // 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.
6354  ImGuiContext& g = *GImGui;
6355  ImGuiWindow* window = g.CurrentWindow;
6356  if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical)
6357  {
6358  ClosePopupToLevel(g.BeginPopupStack.Size, true);
6360  }
6361 
6362  EndPopup();
6363 }
6364 
6365 bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled)
6366 {
6367  ImGuiWindow* window = GetCurrentWindow();
6368  if (window->SkipItems)
6369  return false;
6370 
6371  ImGuiContext& g = *GImGui;
6372  ImGuiStyle& style = g.Style;
6373  ImVec2 pos = window->DC.CursorPos;
6374  ImVec2 label_size = CalcTextSize(label, NULL, true);
6375 
6376  // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
6377  // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
6379  bool pressed;
6380  if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
6381  {
6382  // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
6383  // Note that in this situation we render neither the shortcut neither the selected tick mark
6384  float w = label_size.x;
6385  window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
6387  pressed = Selectable(label, false, flags, ImVec2(w, 0.0f));
6388  PopStyleVar();
6389  window->DC.CursorPos.x += IM_FLOOR(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().
6390  }
6391  else
6392  {
6393  // Menu item inside a vertical menu
6394  // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
6395  // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
6396  float shortcut_w = shortcut ? CalcTextSize(shortcut, NULL).x : 0.0f;
6397  float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame
6398  float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
6399  pressed = Selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
6400  if (shortcut_w > 0.0f)
6401  {
6403  RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false);
6404  PopStyleColor();
6405  }
6406  if (selected)
6407  RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.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);
6408  }
6409 
6410  IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
6411  return pressed;
6412 }
6413 
6414 bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled)
6415 {
6416  if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled))
6417  {
6418  if (p_selected)
6419  *p_selected = !*p_selected;
6420  return true;
6421  }
6422  return false;
6423 }
6424 
6425 //-------------------------------------------------------------------------
6426 // [SECTION] Widgets: BeginTabBar, EndTabBar, etc.
6427 //-------------------------------------------------------------------------
6428 // - BeginTabBar()
6429 // - BeginTabBarEx() [Internal]
6430 // - EndTabBar()
6431 // - TabBarLayout() [Internal]
6432 // - TabBarCalcTabID() [Internal]
6433 // - TabBarCalcMaxTabWidth() [Internal]
6434 // - TabBarFindTabById() [Internal]
6435 // - TabBarRemoveTab() [Internal]
6436 // - TabBarCloseTab() [Internal]
6437 // - TabBarScrollClamp()v
6438 // - TabBarScrollToTab() [Internal]
6439 // - TabBarQueueChangeTabOrder() [Internal]
6440 // - TabBarScrollingButtons() [Internal]
6441 // - TabBarTabListPopupButton() [Internal]
6442 //-------------------------------------------------------------------------
6443 
6444 namespace ImGui
6445 {
6446  static void TabBarLayout(ImGuiTabBar* tab_bar);
6447  static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label);
6448  static float TabBarCalcMaxTabWidth();
6449  static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling);
6450  static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
6453 }
6454 
6456 {
6457  ID = 0;
6460  LastTabContentHeight = 0.0f;
6464  ReorderRequestTabId = 0;
6465  ReorderRequestDir = 0;
6467  LastTabItemIdx = -1;
6468 }
6469 
6470 static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void* lhs, const void* rhs)
6471 {
6472  const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
6473  const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
6474  return (int)(a->Offset - b->Offset);
6475 }
6476 
6478 {
6479  ImGuiContext& g = *GImGui;
6480  return ref.Ptr ? (ImGuiTabBar*)ref.Ptr : g.TabBars.GetByIndex(ref.Index);
6481 }
6482 
6484 {
6485  ImGuiContext& g = *GImGui;
6486  if (g.TabBars.Contains(tab_bar))
6487  return ImGuiPtrOrIndex(g.TabBars.GetIndex(tab_bar));
6488  return ImGuiPtrOrIndex(tab_bar);
6489 }
6490 
6491 bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags)
6492 {
6493  ImGuiContext& g = *GImGui;
6494  ImGuiWindow* window = g.CurrentWindow;
6495  if (window->SkipItems)
6496  return false;
6497 
6498  ImGuiID id = window->GetID(str_id);
6499  ImGuiTabBar* tab_bar = g.TabBars.GetOrAddByKey(id);
6500  ImRect tab_bar_bb = ImRect(window->DC.CursorPos.x, window->DC.CursorPos.y, window->WorkRect.Max.x, window->DC.CursorPos.y + g.FontSize + g.Style.FramePadding.y * 2);
6501  tab_bar->ID = id;
6502  return BeginTabBarEx(tab_bar, tab_bar_bb, flags | ImGuiTabBarFlags_IsFocused);
6503 }
6504 
6506 {
6507  ImGuiContext& g = *GImGui;
6508  ImGuiWindow* window = g.CurrentWindow;
6509  if (window->SkipItems)
6510  return false;
6511 
6512  if ((flags & ImGuiTabBarFlags_DockNode) == 0)
6513  PushOverrideID(tab_bar->ID);
6514 
6515  // Add to stack
6516  g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar));
6517  g.CurrentTabBar = tab_bar;
6518 
6519  if (tab_bar->CurrFrameVisible == g.FrameCount)
6520  {
6521  //IMGUI_DEBUG_LOG("BeginTabBarEx already called this frame\n", g.FrameCount);
6522  IM_ASSERT(0);
6523  return true;
6524  }
6525 
6526  // When toggling back from ordered to manually-reorderable, shuffle tabs to enforce the last visible order.
6527  // 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.
6528  if ((flags & ImGuiTabBarFlags_Reorderable) && !(tab_bar->Flags & ImGuiTabBarFlags_Reorderable) && tab_bar->Tabs.Size > 1 && tab_bar->PrevFrameVisible != -1)
6529  ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByVisibleOffset);
6530 
6531  // Flags
6534 
6535  tab_bar->Flags = flags;
6536  tab_bar->BarRect = tab_bar_bb;
6537  tab_bar->WantLayout = true; // Layout will be done on the first call to ItemTab()
6538  tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible;
6539  tab_bar->CurrFrameVisible = g.FrameCount;
6540  tab_bar->FramePadding = g.Style.FramePadding;
6541 
6542  // Layout
6543  ItemSize(ImVec2(tab_bar->OffsetMaxIdeal, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y);
6544  window->DC.CursorPos.x = tab_bar->BarRect.Min.x;
6545 
6546  // Draw separator
6548  const float y = tab_bar->BarRect.Max.y - 1.0f;
6549  {
6550  const float separator_min_x = tab_bar->BarRect.Min.x - IM_FLOOR(window->WindowPadding.x * 0.5f);
6551  const float separator_max_x = tab_bar->BarRect.Max.x + IM_FLOOR(window->WindowPadding.x * 0.5f);
6552  window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f);
6553  }
6554  return true;
6555 }
6556 
6558 {
6559  ImGuiContext& g = *GImGui;
6560  ImGuiWindow* window = g.CurrentWindow;
6561  if (window->SkipItems)
6562  return;
6563 
6564  ImGuiTabBar* tab_bar = g.CurrentTabBar;
6565  if (tab_bar == NULL)
6566  {
6567  IM_ASSERT_USER_ERROR(tab_bar != NULL, "Mismatched BeginTabBar()/EndTabBar()!");
6568  return;
6569  }
6570  if (tab_bar->WantLayout)
6571  TabBarLayout(tab_bar);
6572 
6573  // Restore the last visible height if no tab is visible, this reduce vertical flicker/movement when a tabs gets removed without calling SetTabItemClosed().
6574  const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
6575  if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing)
6576  tab_bar->LastTabContentHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, 0.0f);
6577  else
6578  window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->LastTabContentHeight;
6579 
6580  if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
6581  PopID();
6582 
6583  g.CurrentTabBarStack.pop_back();
6584  g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back());
6585 }
6586 
6587 // This is called only once a frame before by the first call to ItemTab()
6588 // The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions.
6589 static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
6590 {
6591  ImGuiContext& g = *GImGui;
6592  tab_bar->WantLayout = false;
6593 
6594  // Garbage collect
6595  int tab_dst_n = 0;
6596  for (int tab_src_n = 0; tab_src_n < tab_bar->Tabs.Size; tab_src_n++)
6597  {
6598  ImGuiTabItem* tab = &tab_bar->Tabs[tab_src_n];
6599  if (tab->LastFrameVisible < tab_bar->PrevFrameVisible)
6600  {
6601  if (tab->ID == tab_bar->SelectedTabId)
6602  tab_bar->SelectedTabId = 0;
6603  continue;
6604  }
6605  if (tab_dst_n != tab_src_n)
6606  tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n];
6607  tab_dst_n++;
6608  }
6609  if (tab_bar->Tabs.Size != tab_dst_n)
6610  tab_bar->Tabs.resize(tab_dst_n);
6611 
6612  // Setup next selected tab
6613  ImGuiID scroll_track_selected_tab_id = 0;
6614  if (tab_bar->NextSelectedTabId)
6615  {
6616  tab_bar->SelectedTabId = tab_bar->NextSelectedTabId;
6617  tab_bar->NextSelectedTabId = 0;
6618  scroll_track_selected_tab_id = tab_bar->SelectedTabId;
6619  }
6620 
6621  // Process order change request (we could probably process it when requested but it's just saner to do it in a single spot).
6622  if (tab_bar->ReorderRequestTabId != 0)
6623  {
6624  if (ImGuiTabItem* tab1 = TabBarFindTabByID(tab_bar, tab_bar->ReorderRequestTabId))
6625  {
6626  //IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
6627  int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestDir;
6628  if (tab2_order >= 0 && tab2_order < tab_bar->Tabs.Size)
6629  {
6630  ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order];
6631  ImGuiTabItem item_tmp = *tab1;
6632  *tab1 = *tab2;
6633  *tab2 = item_tmp;
6634  if (tab2->ID == tab_bar->SelectedTabId)
6635  scroll_track_selected_tab_id = tab2->ID;
6636  tab1 = tab2 = NULL;
6637  }
6638  if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings)
6640  }
6641  tab_bar->ReorderRequestTabId = 0;
6642  }
6643 
6644  // Tab List Popup (will alter tab_bar->BarRect and therefore the available width!)
6645  const bool tab_list_popup_button = (tab_bar->Flags & ImGuiTabBarFlags_TabListPopupButton) != 0;
6646  if (tab_list_popup_button)
6647  if (ImGuiTabItem* tab_to_select = TabBarTabListPopupButton(tab_bar)) // NB: Will alter BarRect.Max.x!
6648  scroll_track_selected_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
6649 
6650  // Compute ideal widths
6651  g.ShrinkWidthBuffer.resize(tab_bar->Tabs.Size);
6652  float width_total_contents = 0.0f;
6653  ImGuiTabItem* most_recently_selected_tab = NULL;
6654  bool found_selected_tab_id = false;
6655  for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
6656  {
6657  ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
6658  IM_ASSERT(tab->LastFrameVisible >= tab_bar->PrevFrameVisible);
6659 
6660  if (most_recently_selected_tab == NULL || most_recently_selected_tab->LastFrameSelected < tab->LastFrameSelected)
6661  most_recently_selected_tab = tab;
6662  if (tab->ID == tab_bar->SelectedTabId)
6663  found_selected_tab_id = true;
6664 
6665  // Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
6666  // Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
6667  // and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
6668  const char* tab_name = tab_bar->GetTabName(tab);
6669  const bool has_close_button = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) ? false : true;
6670  tab->ContentWidth = TabItemCalcSize(tab_name, has_close_button).x;
6671 
6672  width_total_contents += (tab_n > 0 ? g.Style.ItemInnerSpacing.x : 0.0f) + tab->ContentWidth;
6673 
6674  // Store data so we can build an array sorted by width if we need to shrink tabs down
6675  g.ShrinkWidthBuffer[tab_n].Index = tab_n;
6676  g.ShrinkWidthBuffer[tab_n].Width = tab->ContentWidth;
6677  }
6678 
6679  // Compute width
6680  const float initial_offset_x = 0.0f; // g.Style.ItemInnerSpacing.x;
6681  const float width_avail = ImMax(tab_bar->BarRect.GetWidth() - initial_offset_x, 0.0f);
6682  float width_excess = (width_avail < width_total_contents) ? (width_total_contents - width_avail) : 0.0f;
6683  if (width_excess > 0.0f && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown))
6684  {
6685  // If we don't have enough room, resize down the largest tabs first
6686  ShrinkWidths(g.ShrinkWidthBuffer.Data, g.ShrinkWidthBuffer.Size, width_excess);
6687  for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
6688  tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index].Width = IM_FLOOR(g.ShrinkWidthBuffer[tab_n].Width);
6689  }
6690  else
6691  {
6692  const float tab_max_width = TabBarCalcMaxTabWidth();
6693  for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
6694  {
6695  ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
6696  tab->Width = ImMin(tab->ContentWidth, tab_max_width);
6697  IM_ASSERT(tab->Width > 0.0f);
6698  }
6699  }
6700 
6701  // Layout all active tabs
6702  float offset_x = initial_offset_x;
6703  float offset_x_ideal = offset_x;
6704  tab_bar->OffsetNextTab = offset_x; // This is used by non-reorderable tab bar where the submission order is always honored.
6705  for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
6706  {
6707  ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
6708  tab->Offset = offset_x;
6709  if (scroll_track_selected_tab_id == 0 && g.NavJustMovedToId == tab->ID)
6710  scroll_track_selected_tab_id = tab->ID;
6711  offset_x += tab->Width + g.Style.ItemInnerSpacing.x;
6712  offset_x_ideal += tab->ContentWidth + g.Style.ItemInnerSpacing.x;
6713  }
6714  tab_bar->OffsetMax = ImMax(offset_x - g.Style.ItemInnerSpacing.x, 0.0f);
6715  tab_bar->OffsetMaxIdeal = ImMax(offset_x_ideal - g.Style.ItemInnerSpacing.x, 0.0f);
6716 
6717  // Horizontal scrolling buttons
6718  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);
6719  if (scrolling_buttons)
6720  if (ImGuiTabItem* tab_to_select = TabBarScrollingButtons(tab_bar)) // NB: Will alter BarRect.Max.x!
6721  scroll_track_selected_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
6722 
6723  // If we have lost the selected tab, select the next most recently active one
6724  if (found_selected_tab_id == false)
6725  tab_bar->SelectedTabId = 0;
6726  if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL)
6727  scroll_track_selected_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID;
6728 
6729  // Lock in visible tab
6730  tab_bar->VisibleTabId = tab_bar->SelectedTabId;
6731  tab_bar->VisibleTabWasSubmitted = false;
6732 
6733  // Update scrolling
6734  if (scroll_track_selected_tab_id)
6735  if (ImGuiTabItem* scroll_track_selected_tab = TabBarFindTabByID(tab_bar, scroll_track_selected_tab_id))
6736  TabBarScrollToTab(tab_bar, scroll_track_selected_tab);
6737  tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
6738  tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
6739  if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
6740  {
6741  // Scrolling speed adjust itself so we can always reach our target in 1/3 seconds.
6742  // Teleport if we are aiming far off the visible line
6743  tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, 70.0f * g.FontSize);
6744  tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, ImFabs(tab_bar->ScrollingTarget - tab_bar->ScrollingAnim) / 0.3f);
6745  const bool teleport = (tab_bar->PrevFrameVisible + 1 < g.FrameCount) || (tab_bar->ScrollingTargetDistToVisibility > 10.0f * g.FontSize);
6746  tab_bar->ScrollingAnim = teleport ? tab_bar->ScrollingTarget : ImLinearSweep(tab_bar->ScrollingAnim, tab_bar->ScrollingTarget, g.IO.DeltaTime * tab_bar->ScrollingSpeed);
6747  }
6748  else
6749  {
6750  tab_bar->ScrollingSpeed = 0.0f;
6751  }
6752 
6753  // Clear name buffers
6754  if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
6755  tab_bar->TabsNames.Buf.resize(0);
6756 }
6757 
6758 // Dockables uses Name/ID in the global namespace. Non-dockable items use the ID stack.
6759 static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label)
6760 {
6761  if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
6762  {
6763  ImGuiID id = ImHashStr(label);
6764  KeepAliveID(id);
6765  return id;
6766  }
6767  else
6768  {
6769  ImGuiWindow* window = GImGui->CurrentWindow;
6770  return window->GetID(label);
6771  }
6772 }
6773 
6775 {
6776  ImGuiContext& g = *GImGui;
6777  return g.FontSize * 20.0f;
6778 }
6779 
6781 {
6782  if (tab_id != 0)
6783  for (int n = 0; n < tab_bar->Tabs.Size; n++)
6784  if (tab_bar->Tabs[n].ID == tab_id)
6785  return &tab_bar->Tabs[n];
6786  return NULL;
6787 }
6788 
6789 // The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
6791 {
6792  if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
6793  tab_bar->Tabs.erase(tab);
6794  if (tab_bar->VisibleTabId == tab_id) { tab_bar->VisibleTabId = 0; }
6795  if (tab_bar->SelectedTabId == tab_id) { tab_bar->SelectedTabId = 0; }
6796  if (tab_bar->NextSelectedTabId == tab_id) { tab_bar->NextSelectedTabId = 0; }
6797 }
6798 
6799 // Called on manual closure attempt
6801 {
6802  if ((tab_bar->VisibleTabId == tab->ID) && !(tab->Flags & ImGuiTabItemFlags_UnsavedDocument))
6803  {
6804  // This will remove a frame of lag for selecting another tab on closure.
6805  // 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
6806  tab->LastFrameVisible = -1;
6807  tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = 0;
6808  }
6809  else if ((tab_bar->VisibleTabId != tab->ID) && (tab->Flags & ImGuiTabItemFlags_UnsavedDocument))
6810  {
6811  // Actually select before expecting closure
6812  tab_bar->NextSelectedTabId = tab->ID;
6813  }
6814 }
6815 
6816 static float ImGui::TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling)
6817 {
6818  scrolling = ImMin(scrolling, tab_bar->OffsetMax - tab_bar->BarRect.GetWidth());
6819  return ImMax(scrolling, 0.0f);
6820 }
6821 
6823 {
6824  ImGuiContext& g = *GImGui;
6825  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)
6826  int order = tab_bar->GetTabOrder(tab);
6827  float tab_x1 = tab->Offset + (order > 0 ? -margin : 0.0f);
6828  float tab_x2 = tab->Offset + tab->Width + (order + 1 < tab_bar->Tabs.Size ? margin : 1.0f);
6829  tab_bar->ScrollingTargetDistToVisibility = 0.0f;
6830  if (tab_bar->ScrollingTarget > tab_x1 || (tab_x2 - tab_x1 >= tab_bar->BarRect.GetWidth()))
6831  {
6832  tab_bar->ScrollingTargetDistToVisibility = ImMax(tab_bar->ScrollingAnim - tab_x2, 0.0f);
6833  tab_bar->ScrollingTarget = tab_x1;
6834  }
6835  else if (tab_bar->ScrollingTarget < tab_x2 - tab_bar->BarRect.GetWidth())
6836  {
6837  tab_bar->ScrollingTargetDistToVisibility = ImMax((tab_x1 - tab_bar->BarRect.GetWidth()) - tab_bar->ScrollingAnim, 0.0f);
6838  tab_bar->ScrollingTarget = tab_x2 - tab_bar->BarRect.GetWidth();
6839  }
6840 }
6841 
6842 void ImGui::TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir)
6843 {
6844  IM_ASSERT(dir == -1 || dir == +1);
6845  IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
6846  tab_bar->ReorderRequestTabId = tab->ID;
6847  tab_bar->ReorderRequestDir = (ImS8)dir;
6848 }
6849 
6851 {
6852  ImGuiContext& g = *GImGui;
6853  ImGuiWindow* window = g.CurrentWindow;
6854 
6855  const ImVec2 arrow_button_size(g.FontSize - 2.0f, g.FontSize + g.Style.FramePadding.y * 2.0f);
6856  const float scrolling_buttons_width = arrow_button_size.x * 2.0f;
6857 
6858  const ImVec2 backup_cursor_pos = window->DC.CursorPos;
6859  //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));
6860 
6861  const ImRect avail_bar_rect = tab_bar->BarRect;
6862  bool want_clip_rect = !avail_bar_rect.Contains(ImRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(scrolling_buttons_width, 0.0f)));
6863  if (want_clip_rect)
6864  PushClipRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max + ImVec2(g.Style.ItemInnerSpacing.x, 0.0f), true);
6865 
6866  ImGuiTabItem* tab_to_select = NULL;
6867 
6868  int select_dir = 0;
6869  ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text];
6870  arrow_col.w *= 0.5f;
6871 
6872  PushStyleColor(ImGuiCol_Text, arrow_col);
6873  PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
6874  const float backup_repeat_delay = g.IO.KeyRepeatDelay;
6875  const float backup_repeat_rate = g.IO.KeyRepeatRate;
6876  g.IO.KeyRepeatDelay = 0.250f;
6877  g.IO.KeyRepeatRate = 0.200f;
6878  window->DC.CursorPos = ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width, tab_bar->BarRect.Min.y);
6880  select_dir = -1;
6881  window->DC.CursorPos = ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width + arrow_button_size.x, tab_bar->BarRect.Min.y);
6883  select_dir = +1;
6884  PopStyleColor(2);
6885  g.IO.KeyRepeatRate = backup_repeat_rate;
6886  g.IO.KeyRepeatDelay = backup_repeat_delay;
6887 
6888  if (want_clip_rect)
6889  PopClipRect();
6890 
6891  if (select_dir != 0)
6892  if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
6893  {
6894  int selected_order = tab_bar->GetTabOrder(tab_item);
6895  int target_order = selected_order + select_dir;
6896  tab_to_select = &tab_bar->Tabs[(target_order >= 0 && target_order < tab_bar->Tabs.Size) ? target_order : selected_order]; // If we are at the end of the list, still scroll to make our tab visible
6897  }
6898  window->DC.CursorPos = backup_cursor_pos;
6899  tab_bar->BarRect.Max.x -= scrolling_buttons_width + 1.0f;
6900 
6901  return tab_to_select;
6902 }
6903 
6905 {
6906  ImGuiContext& g = *GImGui;
6907  ImGuiWindow* window = g.CurrentWindow;
6908 
6909  // We use g.Style.FramePadding.y to match the square ArrowButton size
6910  const float tab_list_popup_button_width = g.FontSize + g.Style.FramePadding.y;
6911  const ImVec2 backup_cursor_pos = window->DC.CursorPos;
6912  window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x - g.Style.FramePadding.y, tab_bar->BarRect.Min.y);
6913  tab_bar->BarRect.Min.x += tab_list_popup_button_width;
6914 
6915  ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text];
6916  arrow_col.w *= 0.5f;
6917  PushStyleColor(ImGuiCol_Text, arrow_col);
6918  PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
6919  bool open = BeginCombo("##v", NULL, ImGuiComboFlags_NoPreview);
6920  PopStyleColor(2);
6921 
6922  ImGuiTabItem* tab_to_select = NULL;
6923  if (open)
6924  {
6925  for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
6926  {
6927  ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
6928  const char* tab_name = tab_bar->GetTabName(tab);
6929  if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID))
6930  tab_to_select = tab;
6931  }
6932  EndCombo();
6933  }
6934 
6935  window->DC.CursorPos = backup_cursor_pos;
6936  return tab_to_select;
6937 }
6938 
6939 //-------------------------------------------------------------------------
6940 // [SECTION] Widgets: BeginTabItem, EndTabItem, etc.
6941 //-------------------------------------------------------------------------
6942 // - BeginTabItem()
6943 // - EndTabItem()
6944 // - TabItemEx() [Internal]
6945 // - SetTabItemClosed()
6946 // - TabItemCalcSize() [Internal]
6947 // - TabItemBackground() [Internal]
6948 // - TabItemLabelAndCloseButton() [Internal]
6949 //-------------------------------------------------------------------------
6950 
6951 bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags)
6952 {
6953  ImGuiContext& g = *GImGui;
6954  ImGuiWindow* window = g.CurrentWindow;
6955  if (window->SkipItems)
6956  return false;
6957 
6958  ImGuiTabBar* tab_bar = g.CurrentTabBar;
6959  if (tab_bar == NULL)
6960  {
6961  IM_ASSERT_USER_ERROR(tab_bar, "BeginTabItem() Needs to be called between BeginTabBar() and EndTabBar()!");
6962  return false;
6963  }
6964  bool ret = TabItemEx(tab_bar, label, p_open, flags);
6965  if (ret && !(flags & ImGuiTabItemFlags_NoPushId))
6966  {
6967  ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
6968  PushOverrideID(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label)
6969  }
6970  return ret;
6971 }
6972 
6974 {
6975  ImGuiContext& g = *GImGui;
6976  ImGuiWindow* window = g.CurrentWindow;
6977  if (window->SkipItems)
6978  return;
6979 
6980  ImGuiTabBar* tab_bar = g.CurrentTabBar;
6981  if (tab_bar == NULL)
6982  {
6983  IM_ASSERT(tab_bar != NULL && "Needs to be called between BeginTabBar() and EndTabBar()!");
6984  return;
6985  }
6986  IM_ASSERT(tab_bar->LastTabItemIdx >= 0);
6987  ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
6988  if (!(tab->Flags & ImGuiTabItemFlags_NoPushId))
6989  window->IDStack.pop_back();
6990 }
6991 
6992 bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags)
6993 {
6994  // Layout whole tab bar if not already done
6995  if (tab_bar->WantLayout)
6996  TabBarLayout(tab_bar);
6997 
6998  ImGuiContext& g = *GImGui;
6999  ImGuiWindow* window = g.CurrentWindow;
7000  if (window->SkipItems)
7001  return false;
7002 
7003  const ImGuiStyle& style = g.Style;
7004  const ImGuiID id = TabBarCalcTabID(tab_bar, label);
7005 
7006  // 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.
7007  if (p_open && !*p_open)
7008  {
7010  ItemAdd(ImRect(), id);
7011  PopItemFlag();
7012  return false;
7013  }
7014 
7015  // Store into ImGuiTabItemFlags_NoCloseButton, also honor ImGuiTabItemFlags_NoCloseButton passed by user (although not documented)
7017  p_open = NULL;
7018  else if (p_open == NULL)
7020 
7021  // Calculate tab contents size
7022  ImVec2 size = TabItemCalcSize(label, p_open != NULL);
7023 
7024  // Acquire tab data
7025  ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, id);
7026  bool tab_is_new = false;
7027  if (tab == NULL)
7028  {
7029  tab_bar->Tabs.push_back(ImGuiTabItem());
7030  tab = &tab_bar->Tabs.back();
7031  tab->ID = id;
7032  tab->Width = size.x;
7033  tab_is_new = true;
7034  }
7035  tab_bar->LastTabItemIdx = (short)tab_bar->Tabs.index_from_ptr(tab);
7036  tab->ContentWidth = size.x;
7037 
7038  const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
7039  const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0;
7040  const bool tab_appearing = (tab->LastFrameVisible + 1 < g.FrameCount);
7041  tab->LastFrameVisible = g.FrameCount;
7042  tab->Flags = flags;
7043 
7044  // Append name with zero-terminator
7045  tab->NameOffset = tab_bar->TabsNames.size();
7046  tab_bar->TabsNames.append(label, label + strlen(label) + 1);
7047 
7048  // If we are not reorderable, always reset offset based on submission order.
7049  // (We already handled layout and sizing using the previous known order, but sizing is not affected by order!)
7050  if (!tab_appearing && !(tab_bar->Flags & ImGuiTabBarFlags_Reorderable))
7051  {
7052  tab->Offset = tab_bar->OffsetNextTab;
7053  tab_bar->OffsetNextTab += tab->Width + g.Style.ItemInnerSpacing.x;
7054  }
7055 
7056  // Update selected tab
7057  if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
7058  if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
7059  tab_bar->NextSelectedTabId = id; // New tabs gets activated
7060  if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // SetSelected can only be passed on explicit tab bar
7061  tab_bar->NextSelectedTabId = id;
7062 
7063  // Lock visibility
7064  bool tab_contents_visible = (tab_bar->VisibleTabId == id);
7065  if (tab_contents_visible)
7066  tab_bar->VisibleTabWasSubmitted = true;
7067 
7068  // On the very first frame of a tab bar we let first tab contents be visible to minimize appearing glitches
7069  if (!tab_contents_visible && tab_bar->SelectedTabId == 0 && tab_bar_appearing)
7070  if (tab_bar->Tabs.Size == 1 && !(tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs))
7071  tab_contents_visible = true;
7072 
7073  if (tab_appearing && !(tab_bar_appearing && !tab_is_new))
7074  {
7076  ItemAdd(ImRect(), id);
7077  PopItemFlag();
7078  return tab_contents_visible;
7079  }
7080 
7081  if (tab_bar->SelectedTabId == id)
7082  tab->LastFrameSelected = g.FrameCount;
7083 
7084  // Backup current layout position
7085  const ImVec2 backup_main_cursor_pos = window->DC.CursorPos;
7086 
7087  // Layout
7088  size.x = tab->Width;
7089  window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_FLOOR(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
7090  ImVec2 pos = window->DC.CursorPos;
7091  ImRect bb(pos, pos + size);
7092 
7093  // 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)
7094  bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x > tab_bar->BarRect.Max.x);
7095  if (want_clip_rect)
7096  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);
7097 
7098  ImVec2 backup_cursor_max_pos = window->DC.CursorMaxPos;
7099  ItemSize(bb.GetSize(), style.FramePadding.y);
7100  window->DC.CursorMaxPos = backup_cursor_max_pos;
7101 
7102  if (!ItemAdd(bb, id))
7103  {
7104  if (want_clip_rect)
7105  PopClipRect();
7106  window->DC.CursorPos = backup_main_cursor_pos;
7107  return tab_contents_visible;
7108  }
7109 
7110  // Click to Select a tab
7112  if (g.DragDropActive)
7114  bool hovered, held;
7115  bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
7116  if (pressed)
7117  tab_bar->NextSelectedTabId = id;
7118  hovered |= (g.HoveredId == id);
7119 
7120  // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
7121  if (!held)
7123 
7124  // Drag and drop: re-order tabs
7125  if (held && !tab_appearing && IsMouseDragging(0))
7126  {
7127  if (!g.DragDropActive && (tab_bar->Flags & ImGuiTabBarFlags_Reorderable))
7128  {
7129  // While moving a tab it will jump on the other side of the mouse, so we also test for MouseDelta.x
7130  if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < bb.Min.x)
7131  {
7132  if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
7133  TabBarQueueChangeTabOrder(tab_bar, tab, -1);
7134  }
7135  else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x)
7136  {
7137  if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
7138  TabBarQueueChangeTabOrder(tab_bar, tab, +1);
7139  }
7140  }
7141  }
7142 
7143 #if 0
7144  if (hovered && g.HoveredIdNotActiveTimer > 0.50f && bb.GetWidth() < tab->ContentWidth)
7145  {
7146  // Enlarge tab display when hovering
7147  bb.Max.x = bb.Min.x + IM_FLOOR(ImLerp(bb.GetWidth(), tab->ContentWidth, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f)));
7148  display_draw_list = GetForegroundDrawList(window);
7149  TabItemBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive));
7150  }
7151 #endif
7152 
7153  // Render tab shape
7154  ImDrawList* display_draw_list = window->DrawList;
7155  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));
7156  TabItemBackground(display_draw_list, bb, flags, tab_col);
7157  RenderNavHighlight(bb, id);
7158 
7159  // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
7160  const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
7161  if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)))
7162  tab_bar->NextSelectedTabId = id;
7163 
7166 
7167  // Render tab label, process close button
7168  const ImGuiID close_button_id = p_open ? window->GetID((void*)((intptr_t)id + 1)) : 0;
7169  bool just_closed = TabItemLabelAndCloseButton(display_draw_list, bb, flags, tab_bar->FramePadding, label, id, close_button_id);
7170  if (just_closed && p_open != NULL)
7171  {
7172  *p_open = false;
7173  TabBarCloseTab(tab_bar, tab);
7174  }
7175 
7176  // Restore main window position so user can draw there
7177  if (want_clip_rect)
7178  PopClipRect();
7179  window->DC.CursorPos = backup_main_cursor_pos;
7180 
7181  // Tooltip (FIXME: Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer)
7182  // We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar (which g.HoveredId ignores)
7183  if (g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > 0.50f && IsItemHovered())
7184  if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip))
7185  SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
7186 
7187  return tab_contents_visible;
7188 }
7189 
7190 // [Public] This is call is 100% optional but it allows to remove some one-frame glitches when a tab has been unexpectedly removed.
7191 // To use it to need to call the function SetTabItemClosed() after BeginTabBar() and before any call to BeginTabItem()
7193 {
7194  ImGuiContext& g = *GImGui;
7195  bool is_within_manual_tab_bar = g.CurrentTabBar && !(g.CurrentTabBar->Flags & ImGuiTabBarFlags_DockNode);
7196  if (is_within_manual_tab_bar)
7197  {
7198  ImGuiTabBar* tab_bar = g.CurrentTabBar;
7199  IM_ASSERT(tab_bar->WantLayout); // Needs to be called AFTER BeginTabBar() and BEFORE the first call to BeginTabItem()
7200  ImGuiID tab_id = TabBarCalcTabID(tab_bar, label);
7201  TabBarRemoveTab(tab_bar, tab_id);
7202  }
7203 }
7204 
7205 ImVec2 ImGui::TabItemCalcSize(const char* label, bool has_close_button)
7206 {
7207  ImGuiContext& g = *GImGui;
7208  ImVec2 label_size = CalcTextSize(label, NULL, true);
7209  ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x, label_size.y + g.Style.FramePadding.y * 2.0f);
7210  if (has_close_button)
7211  size.x += g.Style.FramePadding.x + (g.Style.ItemInnerSpacing.x + g.FontSize); // We use Y intentionally to fit the close button circle.
7212  else
7213  size.x += g.Style.FramePadding.x + 1.0f;
7214  return ImVec2(ImMin(size.x, TabBarCalcMaxTabWidth()), size.y);
7215 }
7216 
7218 {
7219  // 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.
7220  ImGuiContext& g = *GImGui;
7221  const float width = bb.GetWidth();
7222  IM_UNUSED(flags);
7223  IM_ASSERT(width > 0.0f);
7224  const float rounding = ImMax(0.0f, ImMin(g.Style.TabRounding, width * 0.5f - 1.0f));
7225  const float y1 = bb.Min.y + 1.0f;
7226  const float y2 = bb.Max.y - 1.0f;
7227  draw_list->PathLineTo(ImVec2(bb.Min.x, y2));
7228  draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9);
7229  draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12);
7230  draw_list->PathLineTo(ImVec2(bb.Max.x, y2));
7231  draw_list->PathFillConvex(col);
7232  if (g.Style.TabBorderSize > 0.0f)
7233  {
7234  draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2));
7235  draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding + 0.5f, y1 + rounding + 0.5f), rounding, 6, 9);
7236  draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding - 0.5f, y1 + rounding + 0.5f), rounding, 9, 12);
7237  draw_list->PathLineTo(ImVec2(bb.Max.x - 0.5f, y2));
7238  draw_list->PathStroke(GetColorU32(ImGuiCol_Border), false, g.Style.TabBorderSize);
7239  }
7240 }
7241 
7242 // Render text label (with custom clipping) + Unsaved Document marker + Close Button logic
7243 // We tend to lock style.FramePadding for a given tab-bar, hence the 'frame_padding' parameter.
7244 bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id)
7245 {
7246  ImGuiContext& g = *GImGui;
7247  ImVec2 label_size = CalcTextSize(label, NULL, true);
7248  if (bb.GetWidth() <= 1.0f)
7249  return false;
7250 
7251  // Render text label (with clipping + alpha gradient) + unsaved marker
7252  const char* TAB_UNSAVED_MARKER = "*";
7253  ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y);
7255  {
7256  text_pixel_clip_bb.Max.x -= CalcTextSize(TAB_UNSAVED_MARKER, NULL, false).x;
7257  ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + frame_padding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + frame_padding.y + IM_FLOOR(-g.FontSize * 0.25f));
7258  RenderTextClippedEx(draw_list, unsaved_marker_pos, bb.Max - frame_padding, TAB_UNSAVED_MARKER, NULL, NULL);
7259  }
7260  ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
7261 
7262  // Close Button
7263  // We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap()
7264  // 'hovered' will be true when hovering the Tab but NOT when hovering the close button
7265  // 'g.HoveredId==id' will be true when hovering the Tab including when hovering the close button
7266  // 'g.ActiveId==close_button_id' will be true when we are holding on the close button, in which case both hovered booleans are false
7267  bool close_button_pressed = false;
7268  bool close_button_visible = false;
7269  if (close_button_id != 0)
7270  if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == close_button_id)
7271  close_button_visible = true;
7272  if (close_button_visible)
7273  {
7274  ImGuiItemHoveredDataBackup last_item_backup;
7275  const float close_button_sz = g.FontSize;
7276  PushStyleVar(ImGuiStyleVar_FramePadding, frame_padding);
7277  if (CloseButton(close_button_id, ImVec2(bb.Max.x - frame_padding.x * 2.0f - close_button_sz, bb.Min.y)))
7278  close_button_pressed = true;
7279  PopStyleVar();
7280  last_item_backup.Restore();
7281 
7282  // Close with middle mouse button
7284  close_button_pressed = true;
7285 
7286  text_pixel_clip_bb.Max.x -= close_button_sz;
7287  }
7288 
7289  float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.Max.x : bb.Max.x - 1.0f;
7290  RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size);
7291 
7292  return close_button_pressed;
7293 }
7294 
7295 
7296 //-------------------------------------------------------------------------
7297 // [SECTION] Widgets: Columns, BeginColumns, EndColumns, etc.
7298 // In the current version, Columns are very weak. Needs to be replaced with a more full-featured system.
7299 //-------------------------------------------------------------------------
7300 // - GetColumnIndex()
7301 // - GetColumnCount()
7302 // - GetColumnOffset()
7303 // - GetColumnWidth()
7304 // - SetColumnOffset()
7305 // - SetColumnWidth()
7306 // - PushColumnClipRect() [Internal]
7307 // - PushColumnsBackground() [Internal]
7308 // - PopColumnsBackground() [Internal]
7309 // - FindOrCreateColumns() [Internal]
7310 // - GetColumnsID() [Internal]
7311 // - BeginColumns()
7312 // - NextColumn()
7313 // - EndColumns()
7314 // - Columns()
7315 //-------------------------------------------------------------------------
7316 
7318 {
7319  ImGuiWindow* window = GetCurrentWindowRead();
7320  return window->DC.CurrentColumns ? window->DC.CurrentColumns->Current : 0;
7321 }
7322 
7324 {
7325  ImGuiWindow* window = GetCurrentWindowRead();
7326  return window->DC.CurrentColumns ? window->DC.CurrentColumns->Count : 1;
7327 }
7328 
7329 float ImGui::GetColumnOffsetFromNorm(const ImGuiColumns* columns, float offset_norm)
7330 {
7331  return offset_norm * (columns->OffMaxX - columns->OffMinX);
7332 }
7333 
7335 {
7336  return offset / (columns->OffMaxX - columns->OffMinX);
7337 }
7338 
7339 static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f;
7340 
7341 static float GetDraggedColumnOffset(ImGuiColumns* columns, int column_index)
7342 {
7343  // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing
7344  // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning.
7345  ImGuiContext& g = *GImGui;
7346  ImGuiWindow* window = g.CurrentWindow;
7347  IM_ASSERT(column_index > 0); // We are not supposed to drag column 0.
7348  IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index));
7349 
7350  float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + COLUMNS_HIT_RECT_HALF_WIDTH - window->Pos.x;
7351  x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing);
7352  if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths))
7353  x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing);
7354 
7355  return x;
7356 }
7357 
7358 float ImGui::GetColumnOffset(int column_index)
7359 {
7360  ImGuiWindow* window = GetCurrentWindowRead();
7361  ImGuiColumns* columns = window->DC.CurrentColumns;
7362  if (columns == NULL)
7363  return 0.0f;
7364 
7365  if (column_index < 0)
7366  column_index = columns->Current;
7367  IM_ASSERT(column_index < columns->Columns.Size);
7368 
7369  const float t = columns->Columns[column_index].OffsetNorm;
7370  const float x_offset = ImLerp(columns->OffMinX, columns->OffMaxX, t);
7371  return x_offset;
7372 }
7373 
7374 static float GetColumnWidthEx(ImGuiColumns* columns, int column_index, bool before_resize = false)
7375 {
7376  if (column_index < 0)
7377  column_index = columns->Current;
7378 
7379  float offset_norm;
7380  if (before_resize)
7381  offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize;
7382  else
7383  offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm;
7384  return ImGui::GetColumnOffsetFromNorm(columns, offset_norm);
7385 }
7386 
7387 float ImGui::GetColumnWidth(int column_index)
7388 {
7389  ImGuiContext& g = *GImGui;
7390  ImGuiWindow* window = g.CurrentWindow;
7391  ImGuiColumns* columns = window->DC.CurrentColumns;
7392  if (columns == NULL)
7393  return GetContentRegionAvail().x;
7394 
7395  if (column_index < 0)
7396  column_index = columns->Current;
7397  return GetColumnOffsetFromNorm(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm);
7398 }
7399 
7400 void ImGui::SetColumnOffset(int column_index, float offset)
7401 {
7402  ImGuiContext& g = *GImGui;
7403  ImGuiWindow* window = g.CurrentWindow;
7404  ImGuiColumns* columns = window->DC.CurrentColumns;
7405  IM_ASSERT(columns != NULL);
7406 
7407  if (column_index < 0)
7408  column_index = columns->Current;
7409  IM_ASSERT(column_index < columns->Columns.Size);
7410 
7411  const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1);
7412  const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f;
7413 
7414  if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow))
7415  offset = ImMin(offset, columns->OffMaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index));
7416  columns->Columns[column_index].OffsetNorm = GetColumnNormFromOffset(columns, offset - columns->OffMinX);
7417 
7418  if (preserve_width)
7419  SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width));
7420 }
7421 
7422 void ImGui::SetColumnWidth(int column_index, float width)
7423 {
7424  ImGuiWindow* window = GetCurrentWindowRead();
7425  ImGuiColumns* columns = window->DC.CurrentColumns;
7426  IM_ASSERT(columns != NULL);
7427 
7428  if (column_index < 0)
7429  column_index = columns->Current;
7430  SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width);
7431 }
7432 
7433 void ImGui::PushColumnClipRect(int column_index)
7434 {
7435  ImGuiWindow* window = GetCurrentWindowRead();
7436  ImGuiColumns* columns = window->DC.CurrentColumns;
7437  if (column_index < 0)
7438  column_index = columns->Current;
7439 
7440  ImGuiColumnData* column = &columns->Columns[column_index];
7441  PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false);
7442 }
7443 
7444 // Get into the columns background draw command (which is generally the same draw command as before we called BeginColumns)
7446 {
7447  ImGuiWindow* window = GetCurrentWindowRead();
7448  ImGuiColumns* columns = window->DC.CurrentColumns;
7449  if (columns->Count == 1)
7450  return;
7451  columns->Splitter.SetCurrentChannel(window->DrawList, 0);
7452  int cmd_size = window->DrawList->CmdBuffer.Size;
7453  PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false);
7454  IM_UNUSED(cmd_size);
7455  IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd
7456 }
7457 
7459 {
7460  ImGuiWindow* window = GetCurrentWindowRead();
7461  ImGuiColumns* columns = window->DC.CurrentColumns;
7462  if (columns->Count == 1)
7463  return;
7464  columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1);
7465  PopClipRect();
7466 }
7467 
7469 {
7470  // We have few columns per window so for now we don't need bother much with turning this into a faster lookup.
7471  for (int n = 0; n < window->ColumnsStorage.Size; n++)
7472  if (window->ColumnsStorage[n].ID == id)
7473  return &window->ColumnsStorage[n];
7474 
7476  ImGuiColumns* columns = &window->ColumnsStorage.back();
7477  columns->ID = id;
7478  return columns;
7479 }
7480 
7481 ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count)
7482 {
7483  ImGuiWindow* window = GetCurrentWindow();
7484 
7485  // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget.
7486  // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer.
7487  PushID(0x11223347 + (str_id ? 0 : columns_count));
7488  ImGuiID id = window->GetID(str_id ? str_id : "columns");
7489  PopID();
7490 
7491  return id;
7492 }
7493 
7494 void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags)
7495 {
7496  ImGuiContext& g = *GImGui;
7497  ImGuiWindow* window = GetCurrentWindow();
7498 
7499  IM_ASSERT(columns_count >= 1 && columns_count <= 64); // Maximum 64 columns
7500  IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported
7501 
7502  // Acquire storage for the columns set
7503  ImGuiID id = GetColumnsID(str_id, columns_count);
7504  ImGuiColumns* columns = FindOrCreateColumns(window, id);
7505  IM_ASSERT(columns->ID == id);
7506  columns->Current = 0;
7507  columns->Count = columns_count;
7508  columns->Flags = flags;
7509  window->DC.CurrentColumns = columns;
7510 
7511  columns->HostCursorPosY = window->DC.CursorPos.y;
7512  columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x;
7513  columns->HostClipRect = window->ClipRect;
7514  columns->HostWorkRect = window->WorkRect;
7515 
7516  // Set state for first column
7517  // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect
7518  const float column_padding = g.Style.ItemSpacing.x;
7519  const float half_clip_extend_x = ImFloor(ImMax(window->WindowPadding.x * 0.5f, window->WindowBorderSize));
7520  const float max_1 = window->WorkRect.Max.x + column_padding - ImMax(column_padding - window->WindowPadding.x, 0.0f);
7521  const float max_2 = window->WorkRect.Max.x + half_clip_extend_x;
7522  columns->OffMinX = window->DC.Indent.x - column_padding + ImMax(column_padding - window->WindowPadding.x, 0.0f);
7523  columns->OffMaxX = ImMax(ImMin(max_1, max_2) - window->Pos.x, columns->OffMinX + 1.0f);
7524  columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y;
7525 
7526  // Clear data if columns count changed
7527  if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1)
7528  columns->Columns.resize(0);
7529 
7530  // Initialize default widths
7531  columns->IsFirstFrame = (columns->Columns.Size == 0);
7532  if (columns->Columns.Size == 0)
7533  {
7534  columns->Columns.reserve(columns_count + 1);
7535  for (int n = 0; n < columns_count + 1; n++)
7536  {
7537  ImGuiColumnData column;
7538  column.OffsetNorm = n / (float)columns_count;
7539  columns->Columns.push_back(column);
7540  }
7541  }
7542 
7543  for (int n = 0; n < columns_count; n++)
7544  {
7545  // Compute clipping rectangle
7546  ImGuiColumnData* column = &columns->Columns[n];
7547  float clip_x1 = IM_ROUND(window->Pos.x + GetColumnOffset(n));
7548  float clip_x2 = IM_ROUND(window->Pos.x + GetColumnOffset(n + 1) - 1.0f);
7549  column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX);
7550  column->ClipRect.ClipWith(window->ClipRect);
7551  }
7552 
7553  if (columns->Count > 1)
7554  {
7555  columns->Splitter.Split(window->DrawList, 1 + columns->Count);
7556  columns->Splitter.SetCurrentChannel(window->DrawList, 1);
7557  PushColumnClipRect(0);
7558  }
7559 
7560  // We don't generally store Indent.x inside ColumnsOffset because it may be manipulated by the user.
7561  float offset_0 = GetColumnOffset(columns->Current);
7562  float offset_1 = GetColumnOffset(columns->Current + 1);
7563  float width = offset_1 - offset_0;
7564  PushItemWidth(width * 0.65f);
7565  window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f);
7566  window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
7567  window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding;
7568 }
7569 
7571 {
7572  ImGuiWindow* window = GetCurrentWindow();
7573  if (window->SkipItems || window->DC.CurrentColumns == NULL)
7574  return;
7575 
7576  ImGuiContext& g = *GImGui;
7577  ImGuiColumns* columns = window->DC.CurrentColumns;
7578 
7579  if (columns->Count == 1)
7580  {
7581  window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
7582  IM_ASSERT(columns->Current == 0);
7583  return;
7584  }
7585  PopItemWidth();
7586  PopClipRect();
7587 
7588  const float column_padding = g.Style.ItemSpacing.x;
7589  columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
7590  if (++columns->Current < columns->Count)
7591  {
7592  // Columns 1+ ignore IndentX (by canceling it out)
7593  // FIXME-COLUMNS: Unnecessary, could be locked?
7594  window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + column_padding;
7595  columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1);
7596  }
7597  else
7598  {
7599  // New row/line
7600  // Column 0 honor IndentX
7601  window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f);
7602  columns->Splitter.SetCurrentChannel(window->DrawList, 1);
7603  columns->Current = 0;
7604  columns->LineMinY = columns->LineMaxY;
7605  }
7606  window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
7607  window->DC.CursorPos.y = columns->LineMinY;
7608  window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
7609  window->DC.CurrLineTextBaseOffset = 0.0f;
7610 
7611  PushColumnClipRect(columns->Current); // FIXME-COLUMNS: Could it be an overwrite?
7612 
7613  // FIXME-COLUMNS: Share code with BeginColumns() - move code on columns setup.
7614  float offset_0 = GetColumnOffset(columns->Current);
7615  float offset_1 = GetColumnOffset(columns->Current + 1);
7616  float width = offset_1 - offset_0;
7617  PushItemWidth(width * 0.65f);
7618  window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding;
7619 }
7620 
7622 {
7623  ImGuiContext& g = *GImGui;
7624  ImGuiWindow* window = GetCurrentWindow();
7625  ImGuiColumns* columns = window->DC.CurrentColumns;
7626  IM_ASSERT(columns != NULL);
7627 
7628  PopItemWidth();
7629  if (columns->Count > 1)
7630  {
7631  PopClipRect();
7632  columns->Splitter.Merge(window->DrawList);
7633  }
7634 
7635  const ImGuiColumnsFlags flags = columns->Flags;
7636  columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
7637  window->DC.CursorPos.y = columns->LineMaxY;
7639  window->DC.CursorMaxPos.x = columns->HostCursorMaxPosX; // Restore cursor max pos, as columns don't grow parent
7640 
7641  // Draw columns borders and handle resize
7642  // The IsBeingResized flag ensure we preserve pre-resize columns width so back-and-forth are not lossy
7643  bool is_being_resized = false;
7644  if (!(flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
7645  {
7646  // We clip Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.
7647  const float y1 = ImMax(columns->HostCursorPosY, window->ClipRect.Min.y);
7648  const float y2 = ImMin(window->DC.CursorPos.y, window->ClipRect.Max.y);
7649  int dragging_column = -1;
7650  for (int n = 1; n < columns->Count; n++)
7651  {
7652  ImGuiColumnData* column = &columns->Columns[n];
7653  float x = window->Pos.x + GetColumnOffset(n);
7654  const ImGuiID column_id = columns->ID + ImGuiID(n);
7655  const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH;
7656  const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2));
7657  KeepAliveID(column_id);
7658  if (IsClippedEx(column_hit_rect, column_id, false))
7659  continue;
7660 
7661  bool hovered = false, held = false;
7663  {
7664  ButtonBehavior(column_hit_rect, column_id, &hovered, &held);
7665  if (hovered || held)
7666  g.MouseCursor = ImGuiMouseCursor_ResizeEW;
7667  if (held && !(column->Flags & ImGuiColumnsFlags_NoResize))
7668  dragging_column = n;
7669  }
7670 
7671  // Draw column
7673  const float xi = IM_FLOOR(x);
7674  window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col);
7675  }
7676 
7677  // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame.
7678  if (dragging_column != -1)
7679  {
7680  if (!columns->IsBeingResized)
7681  for (int n = 0; n < columns->Count + 1; n++)
7682  columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm;
7683  columns->IsBeingResized = is_being_resized = true;
7684  float x = GetDraggedColumnOffset(columns, dragging_column);
7685  SetColumnOffset(dragging_column, x);
7686  }
7687  }
7688  columns->IsBeingResized = is_being_resized;
7689 
7690  window->WorkRect = columns->HostWorkRect;
7691  window->DC.CurrentColumns = NULL;
7692  window->DC.ColumnsOffset.x = 0.0f;
7693  window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
7694 }
7695 
7696 // [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing]
7697 void ImGui::Columns(int columns_count, const char* id, bool border)
7698 {
7699  ImGuiWindow* window = GetCurrentWindow();
7700  IM_ASSERT(columns_count >= 1);
7701 
7703  //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior
7704  ImGuiColumns* columns = window->DC.CurrentColumns;
7705  if (columns != NULL && columns->Count == columns_count && columns->Flags == flags)
7706  return;
7707 
7708  if (columns != NULL)
7709  EndColumns();
7710 
7711  if (columns_count != 1)
7712  BeginColumns(id, columns_count, flags);
7713 }
7714 
7715 //-------------------------------------------------------------------------
7716 
7717 #endif // #ifndef IMGUI_DISABLE
ImGuiInputTextCallbackData::SelectionStart
int SelectionStart
Definition: imgui.h:1576
IMGUI_CDECL
#define IMGUI_CDECL
Definition: imgui_internal.h:192
ImGuiTabItem::Offset
float Offset
Definition: imgui_internal.h:1600
ImGuiMouseCursor_ResizeEW
@ ImGuiMouseCursor_ResizeEW
Definition: imgui.h:1249
ImGuiKey_Z
@ ImGuiKey_Z
Definition: imgui.h:1008
ImAtan2
#define ImAtan2(Y, X)
Definition: imgui_internal.h:311
ImGui::ClosePopupToLevel
IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup)
Definition: imgui.cpp:7609
ImGuiAxis_Y
@ ImGuiAxis_Y
Definition: imgui_internal.h:586
ImGuiMenuColumns::DeclColumns
float DeclColumns(float w0, float w1, float w2)
Definition: imgui_widgets.cpp:6062
ImGuiDataType_Float
@ ImGuiDataType_Float
Definition: imgui.h:968
ImGuiColumns::LineMaxY
float LineMaxY
Definition: imgui_internal.h:864
ImGui::CalcWindowExpectedSize
IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow *window)
Definition: imgui.cpp:4969
ImGuiCond_Once
@ ImGuiCond_Once
Definition: imgui.h:1268
InputTextFilterCharacter
static bool InputTextFilterCharacter(unsigned int *p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void *user_data)
Definition: imgui_widgets.cpp:3371
ImGuiNextWindowDataFlags_HasSizeConstraint
@ ImGuiNextWindowDataFlags_HasSizeConstraint
Definition: imgui_internal.h:949
ImIsPowerOfTwo
static bool ImIsPowerOfTwo(int v)
Definition: imgui_internal.h:225
ImGuiColumns::Splitter
ImDrawListSplitter Splitter
Definition: imgui_internal.h:870
ImFont::Descent
float Descent
Definition: imgui.h:2293
IMGUI_PAYLOAD_TYPE_COLOR_3F
#define IMGUI_PAYLOAD_TYPE_COLOR_3F
Definition: imgui.h:954
ImGuiMenuColumns::Width
float Width
Definition: imgui_internal.h:761
ImGuiColumns::HostClipRect
ImRect HostClipRect
Definition: imgui_internal.h:867
ImGui::SliderBehavior
IMGUI_API bool SliderBehavior(const ImRect &bb, ImGuiID id, ImGuiDataType data_type, void *p_v, const void *p_min, const void *p_max, const char *format, float power, ImGuiSliderFlags flags, ImRect *out_grab_bb)
Definition: imgui_widgets.cpp:2506
ImGuiWindow::WindowRounding
float WindowRounding
Definition: imgui_internal.h:1467
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:2260
ImGui::ColorPickerOptionsPopup
IMGUI_API void ColorPickerOptionsPopup(const float *ref_col, ImGuiColorEditFlags flags)
Definition: imgui_widgets.cpp:5077
ImGuiCol_TextDisabled
@ ImGuiCol_TextDisabled
Definition: imgui.h:1087
IM_S8_MIN
static const signed char IM_S8_MIN
Definition: imgui_widgets.cpp:85
ImGui::BeginTabBar
IMGUI_API bool BeginTabBar(const char *str_id, ImGuiTabBarFlags flags=0)
Definition: imgui_widgets.cpp:6491
ImGuiComboFlags_HeightMask_
@ ImGuiComboFlags_HeightMask_
Definition: imgui.h:878
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:2255
ImGui::PushItemWidth
IMGUI_API void PushItemWidth(float item_width)
Definition: imgui.cpp:7030
init
WEPOLL_INTERNAL int init(void)
Definition: wepoll.c:858
ImGuiColorEditFlags_InputHSV
@ ImGuiColorEditFlags_InputHSV
Definition: imgui.h:1212
ImGui::InputInt3
IMGUI_API bool InputInt3(const char *label, int v[3], ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:3085
ImGui::EndDragDropSource
IMGUI_API void EndDragDropSource()
Definition: imgui.cpp:9127
ImGuiCol_TitleBgActive
@ ImGuiCol_TitleBgActive
Definition: imgui.h:1097
ImGui::EndMenuBar
IMGUI_API void EndMenuBar()
Definition: imgui_widgets.cpp:6110
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:6489
ImPool::GetByIndex
T * GetByIndex(ImPoolIdx n)
Definition: imgui_internal.h:399
ImGuiColumns::OffMinX
float OffMinX
Definition: imgui_internal.h:863
ImGui::ListBoxFooter
IMGUI_API void ListBoxFooter()
Definition: imgui_widgets.cpp:5772
ImGui::BeginPopup
IMGUI_API bool BeginPopup(const char *str_id, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:7687
STB_TEXTEDIT_K_LEFT
#define STB_TEXTEDIT_K_LEFT
Definition: imgui_widgets.cpp:3267
name
GLuint const GLchar * name
Definition: glcorearb.h:3055
ImGuiInputTextFlags_CallbackResize
@ ImGuiInputTextFlags_CallbackResize
Definition: imgui.h:828
ImGui::TextColored
IMGUI_API void TextColored(const ImVec4 &col, const char *fmt,...) IM_FMTARGS(2)
Definition: imgui_widgets.cpp:266
ImStb::is_separator
static bool is_separator(unsigned int c)
Definition: imgui_widgets.cpp:3208
ImGuiColorEditFlags_HDR
@ ImGuiColorEditFlags_HDR
Definition: imgui.h:1203
ImGuiContext::FontSize
float FontSize
Definition: imgui_internal.h:1025
ImGuiWindow::WindowPadding
ImVec2 WindowPadding
Definition: imgui_internal.h:1466
ImGuiInputTextState::ID
ImGuiID ID
Definition: imgui_internal.h:774
ImGui::PushItemFlag
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled)
Definition: imgui.cpp:6184
ImGui::GetTreeNodeToLabelSpacing
IMGUI_API float GetTreeNodeToLabelSpacing()
Definition: imgui_widgets.cpp:5502
ImPow
static float ImPow(float x, float y)
Definition: imgui_internal.h:315
ImGui::GetFontTexUvWhitePixel
IMGUI_API ImVec2 GetFontTexUvWhitePixel()
Definition: imgui.cpp:6545
ImGuiItemFlags_Disabled
@ ImGuiItemFlags_Disabled
Definition: imgui_internal.h:523
ImStb::STB_TEXTEDIT_GETWIDTH
static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING *obj, int line_start_idx, int char_idx)
Definition: imgui_widgets.cpp:3192
ImDrawCornerFlags_TopRight
@ ImDrawCornerFlags_TopRight
Definition: imgui.h:1935
ImGuiPlotArrayGetterData::Stride
int Stride
Definition: imgui_widgets.cpp:5953
ImGuiIO::KeySuper
bool KeySuper
Definition: imgui.h:1492
ImGuiWindowFlags_NoScrollbar
@ ImGuiWindowFlags_NoScrollbar
Definition: imgui.h:772
ImGuiListClipper
Definition: imgui.h:1785
ImGui::CollapseButton
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2 &pos)
Definition: imgui_widgets.cpp:785
ImGui::ScrollbarEx
IMGUI_API bool ScrollbarEx(const ImRect &bb, ImGuiID id, ImGuiAxis axis, float *p_scroll_v, float avail_v, float contents_v, ImDrawCornerFlags rounding_corners)
Definition: imgui_widgets.cpp:821
ImGuiWindowTempData::CurrentColumns
ImGuiColumns * CurrentColumns
Definition: imgui_internal.h:1402
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:2195
ImGuiIO::KeyCtrl
bool KeyCtrl
Definition: imgui.h:1489
ImGuiPlotArrayGetterData::ImGuiPlotArrayGetterData
ImGuiPlotArrayGetterData(const float *values, int stride)
Definition: imgui_widgets.cpp:5955
ImGuiTabBar::SelectedTabId
ImGuiID SelectedTabId
Definition: imgui_internal.h:1612
ImGui::LabelTextV
IMGUI_API void LabelTextV(const char *label, const char *fmt, va_list args) IM_FMTLIST(2)
Definition: imgui_widgets.cpp:324
ImGui::TextColoredV
IMGUI_API void TextColoredV(const ImVec4 &col, const char *fmt, va_list args) IM_FMTLIST(2)
Definition: imgui_widgets.cpp:274
ImGuiComboFlags_HeightSmall
@ ImGuiComboFlags_HeightSmall
Definition: imgui.h:872
ImGuiInputTextFlags_NoHorizontalScroll
@ ImGuiInputTextFlags_NoHorizontalScroll
Definition: imgui.h:822
ImGuiTabBar::ID
ImGuiID ID
Definition: imgui_internal.h:1611
ImGuiButtonFlags_MouseButtonRight
@ ImGuiButtonFlags_MouseButtonRight
Definition: imgui_internal.h:457
ImGuiColorEditFlags_NoInputs
@ ImGuiColorEditFlags_NoInputs
Definition: imgui.h:1192
ImGui::GetColumnOffset
IMGUI_API float GetColumnOffset(int column_index=-1)
Definition: imgui_widgets.cpp:7358
ImGuiColorEditFlags_NoDragDrop
@ ImGuiColorEditFlags_NoDragDrop
Definition: imgui.h:1196
ImGuiPtrOrIndex
Definition: imgui_internal.h:1005
ImGuiKey
int ImGuiKey
Definition: imgui.h:147
ImGuiSliderFlags_None
@ ImGuiSliderFlags_None
Definition: imgui_internal.h:469
ImGuiInputTextState::CursorAnim
float CursorAnim
Definition: imgui_internal.h:783
ImGui::ColorConvertRGBtoHSV
IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float &out_h, float &out_s, float &out_v)
Definition: imgui.cpp:1831
ImGuiInputSource_Mouse
@ ImGuiInputSource_Mouse
Definition: imgui_internal.h:598
ImGuiDir
int ImGuiDir
Definition: imgui.h:146
ImGuiNextItemData::Flags
ImGuiNextItemDataFlags Flags
Definition: imgui_internal.h:985
ImGuiWindow::MenuBarRect
ImRect MenuBarRect() const
Definition: imgui_internal.h:1558
ImGui::GetColumnWidth
IMGUI_API float GetColumnWidth(int column_index=-1)
Definition: imgui_widgets.cpp:7387
ImGuiNavLayer_Main
@ ImGuiNavLayer_Main
Definition: imgui_internal.h:654
ImGui::GetID
IMGUI_API ImGuiID GetID(const char *str_id)
Definition: imgui.cpp:6656
ImGuiButtonFlags_AlignTextBaseLine
@ ImGuiButtonFlags_AlignTextBaseLine
Definition: imgui_internal.h:451
ImStb::STB_TEXTEDIT_STRINGLEN
static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING *obj)
Definition: imgui_widgets.cpp:3190
ImFont::FontSize
float FontSize
Definition: imgui.h:2277
ImClamp
static T ImClamp(T v, T mn, T mx)
Definition: imgui_internal.h:322
ImGuiInputTextState::Stb
ImStb::STB_TexteditState Stb
Definition: imgui_internal.h:782
ImGuiInputTextFlags_CharsHexadecimal
@ ImGuiInputTextFlags_CharsHexadecimal
Definition: imgui.h:811
IM_U8_MIN
static const unsigned char IM_U8_MIN
Definition: imgui_widgets.cpp:87
ImFabs
#define ImFabs(X)
Definition: imgui_internal.h:305
ImGuiNavLayer_Menu
@ ImGuiNavLayer_Menu
Definition: imgui_internal.h:655
IM_STATIC_ASSERT
IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo)==ImGuiDataType_COUNT)
ImGuiWindowTempData::ItemFlags
ImGuiItemFlags ItemFlags
Definition: imgui_internal.h:1410
ImGuiKey_PageUp
@ ImGuiKey_PageUp
Definition: imgui.h:992
STB_TEXTEDIT_K_UNDO
#define STB_TEXTEDIT_K_UNDO
Definition: imgui_widgets.cpp:3277
ImGui::RadioButton
IMGUI_API bool RadioButton(const char *label, bool active)
Definition: imgui_widgets.cpp:1074
IM_S16_MAX
static const signed short IM_S16_MAX
Definition: imgui_widgets.cpp:90
ImGui::FindOrCreateColumns
IMGUI_API ImGuiColumns * FindOrCreateColumns(ImGuiWindow *window, ImGuiID id)
Definition: imgui_widgets.cpp:7468
ImRect::Expand
void Expand(const float amount)
Definition: imgui_internal.h:707
ImDrawList::PrimReserve
IMGUI_API void PrimReserve(int idx_count, int vtx_count)
Definition: imgui_draw.cpp:539
ImTextStrToUtf8
int ImTextStrToUtf8(char *buf, int buf_size, const ImWchar *in_text, const ImWchar *in_text_end)
Definition: imgui.cpp:1765
ImGuiInputTextState::UserCallback
ImGuiInputTextCallback UserCallback
Definition: imgui_internal.h:787
ImGuiSelectableFlags_DrawHoveredWhenHeld
@ ImGuiSelectableFlags_DrawHoveredWhenHeld
Definition: imgui_internal.h:498
ImGui::ProgressBar
IMGUI_API void ProgressBar(float fraction, const ImVec2 &size_arg=ImVec2(-1, 0), const char *overlay=NULL)
Definition: imgui_widgets.cpp:1135
ImGuiSelectableFlags_SetNavIdOnHover
@ ImGuiSelectableFlags_SetNavIdOnHover
Definition: imgui_internal.h:499
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:2687
ImGui::EndTabBar
IMGUI_API void EndTabBar()
Definition: imgui_widgets.cpp:6557
ImGuiInputTextFlags_CharsDecimal
@ ImGuiInputTextFlags_CharsDecimal
Definition: imgui.h:810
ImGui::RenderArrowPointingAt
IMGUI_API void RenderArrowPointingAt(ImDrawList *draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col)
Definition: imgui_draw.cpp:3252
ImGui::DataTypeApplyOpFromText
IMGUI_API bool DataTypeApplyOpFromText(const char *buf, const char *initial_value_buf, ImGuiDataType data_type, void *p_data, const char *format)
Definition: imgui_widgets.cpp:1785
ImGuiButtonFlags_NoNavFocus
@ ImGuiButtonFlags_NoNavFocus
Definition: imgui_internal.h:454
ImGuiContext::Font
ImFont * Font
Definition: imgui_internal.h:1024
ImU64
unsigned long long ImU64
Definition: imgui.h:204
ImGuiWindowTempData::MenuColumns
ImGuiMenuColumns MenuColumns
Definition: imgui_internal.h:1397
ImGui::GetTextLineHeightWithSpacing
IMGUI_API float GetTextLineHeightWithSpacing()
Definition: imgui.cpp:7111
NULL
NULL
Definition: test_security_zap.cpp:405
g
GLboolean GLboolean g
Definition: glcorearb.h:3228
ImGuiColorEditFlags__InputMask
@ ImGuiColorEditFlags__InputMask
Definition: imgui.h:1222
src
GLenum src
Definition: glcorearb.h:3364
ImGuiNavDirSourceFlags_Keyboard
@ ImGuiNavDirSourceFlags_Keyboard
Definition: imgui_internal.h:628
ImGuiContext::Style
ImGuiStyle Style
Definition: imgui_internal.h:1023
ImRotate
static ImVec2 ImRotate(const ImVec2 &v, float cos_a, float sin_a)
Definition: imgui_internal.h:342
ImGui::PushStyleColor
IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col)
Definition: imgui.cpp:2378
ImGuiCol_Separator
@ ImGuiCol_Separator
Definition: imgui.h:1113
ImGui::LabelText
IMGUI_API void LabelText(const char *label, const char *fmt,...) IM_FMTARGS(2)
Definition: imgui_widgets.cpp:315
ImGuiComboFlags_NoPreview
@ ImGuiComboFlags_NoPreview
Definition: imgui.h:877
ImGuiMouseButton_COUNT
@ ImGuiMouseButton_COUNT
Definition: imgui.h:1237
ImGuiCond
int ImGuiCond
Definition: imgui.h:144
ImGuiCol_SliderGrab
@ ImGuiCol_SliderGrab
Definition: imgui.h:1105
ImGuiCol_PlotHistogram
@ ImGuiCol_PlotHistogram
Definition: imgui.h:1126
ImVec4::z
float z
Definition: imgui.h:223
ImGuiPlotType_Histogram
@ ImGuiPlotType_Histogram
Definition: imgui_internal.h:592
ImGuiDataType_U16
@ ImGuiDataType_U16
Definition: imgui.h:963
ImGui::SetNextWindowPos
IMGUI_API void SetNextWindowPos(const ImVec2 &pos, ImGuiCond cond=0, const ImVec2 &pivot=ImVec2(0, 0))
Definition: imgui.cpp:6470
ImGuiNavInput_COUNT
@ ImGuiNavInput_COUNT
Definition: imgui.h:1053
ImGuiWindow::Flags
ImGuiWindowFlags Flags
Definition: imgui_internal.h:1460
ImGuiTooltipFlags_OverridePreviousTooltip
@ ImGuiTooltipFlags_OverridePreviousTooltip
Definition: imgui_internal.h:561
ImGuiIO::KeyShift
bool KeyShift
Definition: imgui.h:1490
ImGuiCol_HeaderHovered
@ ImGuiCol_HeaderHovered
Definition: imgui.h:1111
ImRect::Min
ImVec2 Min
Definition: imgui_internal.h:686
ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui_widgets.cpp:3215
ImGui::GetCursorScreenPos
IMGUI_API ImVec2 GetCursorScreenPos()
Definition: imgui.cpp:6946
ImGui::FindWindowByName
IMGUI_API ImGuiWindow * FindWindowByName(const char *name)
Definition: imgui.cpp:4831
ImGui::GetColumnsCount
IMGUI_API int GetColumnsCount()
Definition: imgui_widgets.cpp:7323
IMGUI_PAYLOAD_TYPE_COLOR_4F
#define IMGUI_PAYLOAD_TYPE_COLOR_4F
Definition: imgui.h:955
ImGuiTabBar::LastTabItemIdx
short LastTabItemIdx
Definition: imgui_internal.h:1631
ImGui::GetClipboardText
const IMGUI_API char * GetClipboardText()
Definition: imgui.cpp:3226
ImGuiTextBuffer::size
int size() const
Definition: imgui.h:1711
ImGuiNavInput_TweakSlow
@ ImGuiNavInput_TweakSlow
Definition: imgui.h:1043
ImGui::PopColumnsBackground
IMGUI_API void PopColumnsBackground()
Definition: imgui_widgets.cpp:7458
ImGui::BeginMenu
IMGUI_API bool BeginMenu(const char *label, bool enabled=true)
Definition: imgui_widgets.cpp:6185
ImVector::index_from_ptr
int index_from_ptr(const T *it) const
Definition: imgui.h:1355
ImGuiItemHoveredDataBackup
Definition: imgui_internal.h:1562
ImGuiWindow::NavLastIds
ImGuiID NavLastIds[ImGuiNavLayer_COUNT]
Definition: imgui_internal.h:1533
ImGuiInputSource_Nav
@ ImGuiInputSource_Nav
Definition: imgui_internal.h:599
ImGuiInputTextCallbackData::EventKey
ImGuiKey EventKey
Definition: imgui.h:1570
ImGuiInputTextFlags_Multiline
@ ImGuiInputTextFlags_Multiline
Definition: imgui.h:830
ImGuiCol_TextSelectedBg
@ ImGuiCol_TextSelectedBg
Definition: imgui.h:1128
ImGui::Button
IMGUI_API bool Button(const char *label, const ImVec2 &size=ImVec2(0, 0))
Definition: imgui_widgets.cpp:678
ImGui::TabBarCalcMaxTabWidth
static float TabBarCalcMaxTabWidth()
Definition: imgui_widgets.cpp:6774
ImGuiTabBar::NextSelectedTabId
ImGuiID NextSelectedTabId
Definition: imgui_internal.h:1613
ImGui::MarkItemEdited
IMGUI_API void MarkItemEdited(ImGuiID id)
Definition: imgui.cpp:3030
ImGui::IsItemActive
IMGUI_API bool IsItemActive()
Definition: imgui.cpp:4563
ImGui::ColorPicker4
IMGUI_API bool ColorPicker4(const char *label, float col[4], ImGuiColorEditFlags flags=0, const float *ref_col=NULL)
Definition: imgui_widgets.cpp:4510
ImGuiNavInput_TweakFast
@ ImGuiNavInput_TweakFast
Definition: imgui.h:1044
ImGuiWindowFlags
int ImGuiWindowFlags
Definition: imgui.h:168
ImGuiButtonFlags_PressedOnClick
@ ImGuiButtonFlags_PressedOnClick
Definition: imgui_internal.h:441
s
XmlRpcServer s
ImFont::ContainerAtlas
ImFontAtlas * ContainerAtlas
Definition: imgui.h:2286
ImGuiButtonFlags_NoHoldingActiveId
@ ImGuiButtonFlags_NoHoldingActiveId
Definition: imgui_internal.h:453
ImGuiSeparatorFlags
int ImGuiSeparatorFlags
Definition: imgui_internal.h:113
ImGuiTabBar::PrevFrameVisible
int PrevFrameVisible
Definition: imgui_internal.h:1616
ImGui::CalcItemSize
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h)
Definition: imgui.cpp:7084
ImGuiWindowTempData::NavLayerActiveMaskNext
int NavLayerActiveMaskNext
Definition: imgui_internal.h:1389
ImGuiColorEditFlags__DataTypeMask
@ ImGuiColorEditFlags__DataTypeMask
Definition: imgui.h:1220
ImFormatString
int ImFormatString(char *buf, size_t buf_size, const char *fmt,...)
Definition: imgui.cpp:1437
ImGuiShrinkWidthItem::Width
float Width
Definition: imgui_internal.h:1002
ImGui::SetNextItemWidth
IMGUI_API void SetNextItemWidth(float item_width)
Definition: imgui.cpp:7023
ImGuiButtonFlags_MouseButtonLeft
@ ImGuiButtonFlags_MouseButtonLeft
Definition: imgui_internal.h:456
ImGuiNavInput_Activate
@ ImGuiNavInput_Activate
Definition: imgui.h:1029
ImGuiButtonFlags_Disabled
@ ImGuiButtonFlags_Disabled
Definition: imgui_internal.h:450
ImGuiTabBarFlags
int ImGuiTabBarFlags
Definition: imgui.h:165
ImGuiDataTypeInfo::Size
size_t Size
Definition: imgui_internal.h:721
ImGui::SeparatorEx
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags)
Definition: imgui_widgets.cpp:1254
ImGui::SetColorEditOptions
IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags)
Definition: imgui_widgets.cpp:4973
STB_TexteditState::has_preferred_x
unsigned char has_preferred_x
Definition: imstb_textedit.h:346
ImGui::CalcTypematicRepeatAmount
IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate)
Definition: imgui.cpp:4380
ImGuiWindowTempData::NavLayerCurrent
ImGuiNavLayer NavLayerCurrent
Definition: imgui_internal.h:1386
ImGuiStyleVar_ChildRounding
@ ImGuiStyleVar_ChildRounding
Definition: imgui.h:1159
ImGui::PopStyleColor
IMGUI_API void PopStyleColor(int count=1)
Definition: imgui.cpp:2398
label
GLuint GLsizei const GLchar * label
Definition: glcorearb.h:4316
ImGuiNextWindowData::MenuBarOffsetMinVal
ImVec2 MenuBarOffsetMinVal
Definition: imgui_internal.h:970
ImGuiNavInput_Cancel
@ ImGuiNavInput_Cancel
Definition: imgui.h:1030
ImGui::ItemHoverable
IMGUI_API bool ItemHoverable(const ImRect &bb, ImGuiID id)
Definition: imgui.cpp:3107
ImGuiWindowTempData::ColumnsOffset
ImVec1 ColumnsOffset
Definition: imgui_internal.h:1376
GDataTypeInfo
static const ImGuiDataTypeInfo GDataTypeInfo[]
Definition: imgui_widgets.cpp:1660
ImGuiKey_Enter
@ ImGuiKey_Enter
Definition: imgui.h:1000
GetColumnWidthEx
static float GetColumnWidthEx(ImGuiColumns *columns, int column_index, bool before_resize=false)
Definition: imgui_widgets.cpp:7374
ImGuiInputTextCallbackData::EventFlag
ImGuiInputTextFlags EventFlag
Definition: imgui.h:1562
ImDrawCornerFlags_TopLeft
@ ImDrawCornerFlags_TopLeft
Definition: imgui.h:1934
ImGuiInputTextState::CursorFollow
bool CursorFollow
Definition: imgui_internal.h:784
ImGuiKey_Delete
@ ImGuiKey_Delete
Definition: imgui.h:997
ImGuiTabBarFlags_AutoSelectNewTabs
@ ImGuiTabBarFlags_AutoSelectNewTabs
Definition: imgui.h:886
ImGuiPlotArrayGetterData
Definition: imgui_widgets.cpp:5950
ImGuiInputTextCallbackData::CursorPos
int CursorPos
Definition: imgui.h:1575
ImHashStr
ImU32 ImHashStr(const char *data_p, size_t data_size, ImU32 seed)
Definition: imgui.cpp:1513
ImGui::SetScrollY
IMGUI_API void SetScrollY(float scroll_y)
Definition: imgui.cpp:7360
ImGuiWindowTempData::LastItemDisplayRect
ImRect LastItemDisplayRect
Definition: imgui_internal.h:1383
ImGuiInputTextFlags_CallbackHistory
@ ImGuiInputTextFlags_CallbackHistory
Definition: imgui.h:817
STB_TEXTEDIT_K_WORDRIGHT
#define STB_TEXTEDIT_K_WORDRIGHT
Definition: imgui_widgets.cpp:3280
active
@ active
Definition: proxy.cpp:141
ImGuiKey_X
@ ImGuiKey_X
Definition: imgui.h:1006
ImVec1::x
float x
Definition: imgui_internal.h:668
ImDrawList::AddRectFilled
IMGUI_API void AddRectFilled(const ImVec2 &p_min, const ImVec2 &p_max, ImU32 col, float rounding=0.0f, ImDrawCornerFlags rounding_corners=ImDrawCornerFlags_All)
Definition: imgui_draw.cpp:1033
ImGui::ListBoxHeader
IMGUI_API bool ListBoxHeader(const char *label, const ImVec2 &size=ImVec2(0, 0))
Definition: imgui_widgets.cpp:5718
ImGui::Dummy
IMGUI_API void Dummy(const ImVec2 &size)
Definition: imgui_widgets.cpp:1215
ImGuiContext::CurrentTabBar
ImGuiTabBar * CurrentTabBar
Definition: imgui_internal.h:1170
ImGui::DragBehaviorT
IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T *v, float v_speed, T v_min, T v_max, const char *format, float power, ImGuiDragFlags flags)
ImGuiSelectableFlags_SpanAvailWidth
@ ImGuiSelectableFlags_SpanAvailWidth
Definition: imgui_internal.h:497
ImGui::LogText
IMGUI_API void LogText(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui.cpp:9310
ImGuiInputTextState::CursorAnimReset
void CursorAnimReset()
Definition: imgui_internal.h:798
ImGuiTabBarFlags_DockNode
@ ImGuiTabBarFlags_DockNode
Definition: imgui_internal.h:1581
ImFloor
static float ImFloor(float f)
Definition: imgui_internal.h:338
ImGuiContext::NextWindowData
ImGuiNextWindowData NextWindowData
Definition: imgui_internal.h:1080
ImGuiTabBar::FramePadding
ImVec2 FramePadding
Definition: imgui_internal.h:1632
ImGuiWindow::ParentWindow
ImGuiWindow * ParentWindow
Definition: imgui_internal.h:1527
ImDrawList
Definition: imgui.h:1961
ImGuiColorEditFlags_NoSidePreview
@ ImGuiColorEditFlags_NoSidePreview
Definition: imgui.h:1195
ImGuiDataType_S32
@ ImGuiDataType_S32
Definition: imgui.h:964
ImGuiColorEditFlags__OptionsDefault
@ ImGuiColorEditFlags__OptionsDefault
Definition: imgui.h:1216
ImGuiInputTextFlags_CharsScientific
@ ImGuiInputTextFlags_CharsScientific
Definition: imgui.h:827
ImGuiInputTextState::InitialTextA
ImVector< char > InitialTextA
Definition: imgui_internal.h:778
ImStb::STB_TEXTEDIT_GETCHAR
static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui_widgets.cpp:3191
ImTextureID
void * ImTextureID
Definition: imgui.h:172
ImGuiInputTextState::UserCallbackData
void * UserCallbackData
Definition: imgui_internal.h:788
ImGuiKey_RightArrow
@ ImGuiKey_RightArrow
Definition: imgui.h:989
ids
GLuint * ids
Definition: glcorearb.h:2931
ImAtof
#define ImAtof(STR)
Definition: imgui_internal.h:312
ImGuiInputTextState::OnKeyPressed
void OnKeyPressed(int key)
Definition: imgui_widgets.cpp:3305
STB_TEXTEDIT_GETWIDTH_NEWLINE
#define STB_TEXTEDIT_GETWIDTH_NEWLINE
Definition: imgui_internal.h:129
ImGuiColorEditFlags_AlphaPreview
@ ImGuiColorEditFlags_AlphaPreview
Definition: imgui.h:1201
ImRect::GetSize
ImVec2 GetSize() const
Definition: imgui_internal.h:695
ImDrawCornerFlags_All
@ ImDrawCornerFlags_All
Definition: imgui.h:1942
ImTriangleClosestPoint
ImVec2 ImTriangleClosestPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p)
Definition: imgui.cpp:1281
ImGuiWindow::Collapsed
bool Collapsed
Definition: imgui_internal.h:1481
ImGuiInputReadMode_Repeat
@ ImGuiInputReadMode_Repeat
Definition: imgui_internal.h:611
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:2215
ImFont::IndexAdvanceX
ImVector< float > IndexAdvanceX
Definition: imgui.h:2275
ImGui::BeginColumns
IMGUI_API void BeginColumns(const char *str_id, int count, ImGuiColumnsFlags flags=0)
Definition: imgui_widgets.cpp:7494
ImGuiAxis_X
@ ImGuiAxis_X
Definition: imgui_internal.h:585
ImGui::PushFont
IMGUI_API void PushFont(ImFont *font)
Definition: imgui.cpp:6166
ImGuiWindowTempData::StateStorage
ImGuiStorage * StateStorage
Definition: imgui_internal.h:1401
ImGuiInputTextState::ScrollX
float ScrollX
Definition: imgui_internal.h:781
ImGuiTabBarFlags_FittingPolicyScroll
@ ImGuiTabBarFlags_FittingPolicyScroll
Definition: imgui.h:892
ImS8
signed char ImS8
Definition: imgui.h:189
ImGui::Unindent
IMGUI_API void Unindent(float indent_w=0.0f)
Definition: imgui.cpp:7014
ImGui::Text
IMGUI_API void Text(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui_widgets.cpp:247
ImGuiTabBar::TabsNames
ImGuiTextBuffer TabsNames
Definition: imgui_internal.h:1633
ImGui::InvisibleButton
IMGUI_API bool InvisibleButton(const char *str_id, const ImVec2 &size)
Definition: imgui_widgets.cpp:696
if
PHP_PROTO_OBJECT_FREE_END PHP_PROTO_OBJECT_DTOR_END if(!upb_strtable_init(&intern->table, UPB_CTYPE_UINT64))
Definition: php/ext/google/protobuf/map.c:232
H
#define H(n)
Definition: sha1.c:52
ShrinkWidthItemComparer
static int IMGUI_CDECL ShrinkWidthItemComparer(const void *lhs, const void *rhs)
Definition: imgui_widgets.cpp:1382
ImGuiWindowFlags_Popup
@ ImGuiWindowFlags_Popup
Definition: imgui.h:797
ImGuiCol_Button
@ ImGuiCol_Button
Definition: imgui.h:1107
ImGuiColorEditFlags_NoPicker
@ ImGuiColorEditFlags_NoPicker
Definition: imgui.h:1189
ImGuiColorEditFlags_DisplayRGB
@ ImGuiColorEditFlags_DisplayRGB
Definition: imgui.h:1204
ImGuiID
unsigned int ImGuiID
Definition: imgui.h:174
ImGuiTabBarFlags_SaveSettings
@ ImGuiTabBarFlags_SaveSettings
Definition: imgui_internal.h:1583
ImFont::IndexLookup
ImVector< ImWchar > IndexLookup
Definition: imgui.h:2280
ImGuiNavHighlightFlags
int ImGuiNavHighlightFlags
Definition: imgui_internal.h:108
ImGuiMenuColumns::NextWidths
float NextWidths[3]
Definition: imgui_internal.h:762
ImGuiCol_ScrollbarGrabHovered
@ ImGuiCol_ScrollbarGrabHovered
Definition: imgui.h:1102
ImGui::TabBarFindTabByID
IMGUI_API ImGuiTabItem * TabBarFindTabByID(ImGuiTabBar *tab_bar, ImGuiID tab_id)
Definition: imgui_widgets.cpp:6780
ImGuiStyle::Alpha
float Alpha
Definition: imgui.h:1367
ImGuiTabBar::LastTabContentHeight
float LastTabContentHeight
Definition: imgui_internal.h:1618
STB_TEXTEDIT_K_LINEEND
#define STB_TEXTEDIT_K_LINEEND
Definition: imgui_widgets.cpp:3272
ImTextCountUtf8BytesFromStr
int ImTextCountUtf8BytesFromStr(const ImWchar *in_text, const ImWchar *in_text_end)
Definition: imgui.cpp:1781
ImGuiNavLayer
ImGuiNavLayer
Definition: imgui_internal.h:652
ImGui::NavMoveRequestCancel
IMGUI_API void NavMoveRequestCancel()
Definition: imgui.cpp:8194
ImGuiColumnsFlags_NoBorder
@ ImGuiColumnsFlags_NoBorder
Definition: imgui_internal.h:483
ImVector< ImWchar >
ImGui::SameLine
IMGUI_API void SameLine(float offset_from_start_x=0.0f, float spacing=-1.0f)
Definition: imgui.cpp:6923
ImGuiWindowTempData::NavFocusScopeIdCurrent
ImGuiID NavFocusScopeIdCurrent
Definition: imgui_internal.h:1390
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:5572
ImGuiWindowFlags_AlwaysAutoResize
@ ImGuiWindowFlags_AlwaysAutoResize
Definition: imgui.h:775
ImFontGlyph
Definition: imgui.h:2120
ImGuiTabBar
Definition: imgui_internal.h:1608
ImGuiColumns::IsBeingResized
bool IsBeingResized
Definition: imgui_internal.h:860
y
GLint y
Definition: glcorearb.h:2768
ImGuiStyleVar_ItemSpacing
@ ImGuiStyleVar_ItemSpacing
Definition: imgui.h:1166
ImGui::SmallButton
IMGUI_API bool SmallButton(const char *label)
Definition: imgui_widgets.cpp:684
ImGuiCol_Header
@ ImGuiCol_Header
Definition: imgui.h:1110
ImDrawListSplitter::Merge
IMGUI_API void Merge(ImDrawList *draw_list)
Definition: imgui_draw.cpp:1356
ImGui::TabBarCalcTabID
static ImU32 TabBarCalcTabID(ImGuiTabBar *tab_bar, const char *label)
Definition: imgui_widgets.cpp:6759
ImGuiTextBuffer::Buf
ImVector< char > Buf
Definition: imgui.h:1704
ImGuiTabItemFlags_NoCloseButton
@ ImGuiTabItemFlags_NoCloseButton
Definition: imgui_internal.h:1589
ImGui::FocusableItemRegister
IMGUI_API bool FocusableItemRegister(ImGuiWindow *window, ImGuiID id)
Definition: imgui.cpp:3152
ImGuiInputTextCallbackData::BufTextLen
int BufTextLen
Definition: imgui.h:1572
ImGui::GetColumnOffsetFromNorm
IMGUI_API float GetColumnOffsetFromNorm(const ImGuiColumns *columns, float offset_norm)
Definition: imgui_widgets.cpp:7329
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:2250
ImGui::ClearActiveID
IMGUI_API void ClearActiveID()
Definition: imgui.cpp:3001
alpha
GLfloat GLfloat GLfloat alpha
Definition: glcorearb.h:2777
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:2574
ImGuiSliderFlags
int ImGuiSliderFlags
Definition: imgui_internal.h:114
ImVec2
Definition: imgui.h:208
ImGui::FocusTopMostWindowUnderOne
IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow *under_this_window, ImGuiWindow *ignore_window)
Definition: imgui.cpp:6125
ImGuiKey_End
@ ImGuiKey_End
Definition: imgui.h:995
ImGuiIO::KeyAlt
bool KeyAlt
Definition: imgui.h:1491
x
GLint GLenum GLint x
Definition: glcorearb.h:2834
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:2761
ImGuiContext::TabBars
ImPool< ImGuiTabBar > TabBars
Definition: imgui_internal.h:1171
ImTriangleContainsPoint
bool ImTriangleContainsPoint(const ImVec2 &a, const ImVec2 &b, const ImVec2 &c, const ImVec2 &p)
Definition: imgui.cpp:1262
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:2646
ImGuiColumns::Columns
ImVector< ImGuiColumnData > Columns
Definition: imgui_internal.h:869
IM_UNUSED
#define IM_UNUSED(_VAR)
Definition: imgui.h:89
ImGuiInputTextState::TextAIsValid
bool TextAIsValid
Definition: imgui_internal.h:779
STB_TEXTEDIT_K_REDO
#define STB_TEXTEDIT_K_REDO
Definition: imgui_widgets.cpp:3278
ImRect::Max
ImVec2 Max
Definition: imgui_internal.h:687
ImGuiWindowFlags_MenuBar
@ ImGuiWindowFlags_MenuBar
Definition: imgui.h:779
ImGuiPopupPositionPolicy_ComboBox
@ ImGuiPopupPositionPolicy_ComboBox
Definition: imgui_internal.h:662
ImGuiWindowTempData::CursorPos
ImVec2 CursorPos
Definition: imgui_internal.h:1367
ImGuiSelectableFlags_SelectOnClick
@ ImGuiSelectableFlags_SelectOnClick
Definition: imgui_internal.h:495
ImGuiCol_HeaderActive
@ ImGuiCol_HeaderActive
Definition: imgui.h:1112
ImGui::TabItemCalcSize
IMGUI_API ImVec2 TabItemCalcSize(const char *label, bool has_close_button)
Definition: imgui_widgets.cpp:7205
Plot_ArrayGetter
static float Plot_ArrayGetter(void *data, int idx)
Definition: imgui_widgets.cpp:5958
ImGui::RenderNavHighlight
IMGUI_API void RenderNavHighlight(const ImRect &bb, ImGuiID id, ImGuiNavHighlightFlags flags=ImGuiNavHighlightFlags_TypeDefault)
Definition: imgui.cpp:2768
ImDrawList::AddRectFilledMultiColor
IMGUI_API void AddRectFilledMultiColor(const ImVec2 &p_min, const ImVec2 &p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left)
Definition: imgui_draw.cpp:1050
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:3116
ImGuiButtonFlags_PressedOnRelease
@ ImGuiButtonFlags_PressedOnRelease
Definition: imgui_internal.h:444
ImGui::PushTextWrapPos
IMGUI_API void PushTextWrapPos(float wrap_local_pos_x=0.0f)
Definition: imgui.cpp:6222
ImRect::Overlaps
bool Overlaps(const ImRect &r) const
Definition: imgui_internal.h:704
ImGuiWindowFlags_NoSavedSettings
@ ImGuiWindowFlags_NoSavedSettings
Definition: imgui.h:777
IM_S32_MIN
static const ImS32 IM_S32_MIN
Definition: imgui_widgets.cpp:93
ImGuiTreeNodeFlags_Framed
@ ImGuiTreeNodeFlags_Framed
Definition: imgui.h:839
ImS32
signed int ImS32
Definition: imgui.h:193
ImGui::BeginDragDropSource
IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags=0)
Definition: imgui.cpp:9024
ImAddClampOverflow
static T ImAddClampOverflow(T a, T b, T mn, T mx)
Definition: imgui_internal.h:325
ImGuiButtonFlags
int ImGuiButtonFlags
Definition: imgui_internal.h:103
ImGuiComboFlags_PopupAlignLeft
@ ImGuiComboFlags_PopupAlignLeft
Definition: imgui.h:871
ImGui::GetColumnIndex
IMGUI_API int GetColumnIndex()
Definition: imgui_widgets.cpp:7317
ImStb
Definition: imgui_internal.h:122
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:1681
ImGuiWindowTempData::GroupStack
ImVector< ImGuiGroupData > GroupStack
Definition: imgui_internal.h:1416
ImGui::CheckboxFlags
IMGUI_API bool CheckboxFlags(const char *label, unsigned int *flags, unsigned int flags_value)
Definition: imgui_widgets.cpp:1059
ImGui::SetMouseCursor
IMGUI_API void SetMouseCursor(ImGuiMouseCursor cursor_type)
Definition: imgui.cpp:4548
ImGuiInputTextState::CurLenW
int CurLenW
Definition: imgui_internal.h:775
ImMin
static T ImMin(T lhs, T rhs)
Definition: imgui_internal.h:320
idx
static uint32_t idx(tarjan *t, const upb_refcounted *r)
Definition: ruby/ext/google/protobuf_c/upb.c:5925
ImGuiWindowFlags_ChildMenu
@ ImGuiWindowFlags_ChildMenu
Definition: imgui.h:799
ImDrawList::CmdBuffer
ImVector< ImDrawCmd > CmdBuffer
Definition: imgui.h:1964
ImGui::BulletTextV
IMGUI_API void BulletTextV(const char *fmt, va_list args) IM_FMTLIST(1)
Definition: imgui_widgets.cpp:358
ImGui::IsNavInputTest
bool IsNavInputTest(ImGuiNavInput n, ImGuiInputReadMode rm)
Definition: imgui_internal.h:1779
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:1325
ImGuiTabBar::Tabs
ImVector< ImGuiTabItem > Tabs
Definition: imgui_internal.h:1610
ImGuiStyleVar_ChildBorderSize
@ ImGuiStyleVar_ChildBorderSize
Definition: imgui.h:1160
ImGui::SliderScalar
IMGUI_API bool SliderScalar(const char *label, ImGuiDataType data_type, void *p_data, const void *p_min, const void *p_max, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:2540
flags
GLbitfield flags
Definition: glcorearb.h:3585
ImGuiTabBarFlags_FittingPolicyResizeDown
@ ImGuiTabBarFlags_FittingPolicyResizeDown
Definition: imgui.h:891
ImGuiColorEditFlags_NoTooltip
@ ImGuiColorEditFlags_NoTooltip
Definition: imgui.h:1193
ImGuiInputTextState
Definition: imgui_internal.h:772
ImGui::EndCombo
IMGUI_API void EndCombo()
Definition: imgui_widgets.cpp:1551
ImGui::GetCurrentWindow
ImGuiWindow * GetCurrentWindow()
Definition: imgui_internal.h:1657
ImGuiHoveredFlags_AllowWhenBlockedByPopup
@ ImGuiHoveredFlags_AllowWhenBlockedByPopup
Definition: imgui.h:926
ImGuiTreeNodeFlags
int ImGuiTreeNodeFlags
Definition: imgui.h:167
ImGui::BeginChildEx
IMGUI_API bool BeginChildEx(const char *name, ImGuiID id, const ImVec2 &size_arg, bool border, ImGuiWindowFlags flags)
Definition: imgui.cpp:4692
ImGui::TreeNodeV
IMGUI_API bool TreeNodeV(const char *str_id, const char *fmt, va_list args) IM_FMTLIST(2)
Definition: imgui_widgets.cpp:5156
imgui_internal.h
ImGuiStyle::ItemSpacing
ImVec2 ItemSpacing
Definition: imgui.h:1381
ImGuiTabBarFlags_TabListPopupButton
@ ImGuiTabBarFlags_TabListPopupButton
Definition: imgui.h:887
IM_U16_MAX
static const unsigned short IM_U16_MAX
Definition: imgui_widgets.cpp:92
ImGuiStyle::SelectableTextAlign
ImVec2 SelectableTextAlign
Definition: imgui.h:1394
ImDrawList::AddText
IMGUI_API void AddText(const ImVec2 &pos, ImU32 col, const char *text_begin, const char *text_end=NULL)
Definition: imgui_draw.cpp:1235
ImGui::InputInt2
IMGUI_API bool InputInt2(const char *label, int v[2], ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:3080
ImGui::ColorEdit4
IMGUI_API bool ColorEdit4(const char *label, float col[4], ImGuiColorEditFlags flags=0)
Definition: imgui_widgets.cpp:4250
ImGuiInputTextFlags_CharsNoBlank
@ ImGuiInputTextFlags_CharsNoBlank
Definition: imgui.h:813
ImGuiColorEditFlags
int ImGuiColorEditFlags
Definition: imgui.h:156
ImGuiTabBarFlags_NoCloseWithMiddleMouseButton
@ ImGuiTabBarFlags_NoCloseWithMiddleMouseButton
Definition: imgui.h:888
ImGuiInputTextFlags_Password
@ ImGuiInputTextFlags_Password
Definition: imgui.h:825
ImGuiTabBarFlags_None
@ ImGuiTabBarFlags_None
Definition: imgui.h:884
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:2657
b
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:3228
ImGuiStyle::FrameRounding
float FrameRounding
Definition: imgui.h:1379
ImGuiStyle::ColorButtonPosition
ImGuiDir ColorButtonPosition
Definition: imgui.h:1392
IM_U8_MAX
static const unsigned char IM_U8_MAX
Definition: imgui_widgets.cpp:88
ImGuiCol_ScrollbarGrab
@ ImGuiCol_ScrollbarGrab
Definition: imgui.h:1101
ImGuiInputTextState::BufCapacityA
int BufCapacityA
Definition: imgui_internal.h:780
ImGui::TextDisabledV
IMGUI_API void TextDisabledV(const char *fmt, va_list args) IM_FMTLIST(1)
Definition: imgui_widgets.cpp:289
ImGuiKey_A
@ ImGuiKey_A
Definition: imgui.h:1003
ImGuiKey_Home
@ ImGuiKey_Home
Definition: imgui.h:994
ImGui::IsPopupOpen
IMGUI_API bool IsPopupOpen(const char *str_id)
Definition: imgui.cpp:7503
ImGuiItemFlags_NoNavDefaultFocus
@ ImGuiItemFlags_NoNavDefaultFocus
Definition: imgui_internal.h:525
ImGuiCol_PlotLinesHovered
@ ImGuiCol_PlotLinesHovered
Definition: imgui.h:1125
ImGuiTextFlags_NoWidthForLargeClippedText
@ ImGuiTextFlags_NoWidthForLargeClippedText
Definition: imgui_internal.h:555
ImGuiInputReadMode_RepeatFast
@ ImGuiInputReadMode_RepeatFast
Definition: imgui_internal.h:613
ImGui::IsItemHovered
IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags=0)
Definition: imgui.cpp:3065
ImGuiInputTextFlags_CallbackCompletion
@ ImGuiInputTextFlags_CallbackCompletion
Definition: imgui.h:816
ImGuiWindowTempData::LastItemStatusFlags
ImGuiItemStatusFlags LastItemStatusFlags
Definition: imgui_internal.h:1381
ImGui::Separator
IMGUI_API void Separator()
Definition: imgui_widgets.cpp:1311
values
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:3591
IM_U32_MAX
static const ImU32 IM_U32_MAX
Definition: imgui_widgets.cpp:96
ImGuiKey_COUNT
@ ImGuiKey_COUNT
Definition: imgui.h:1009
ImGui::CalcWrapWidthForPos
IMGUI_API float CalcWrapWidthForPos(const ImVec2 &pos, float wrap_pos_x)
Definition: imgui.cpp:3195
ImGuiCol_FrameBgActive
@ ImGuiCol_FrameBgActive
Definition: imgui.h:1095
ImGuiDataTypeInfo
Definition: imgui_internal.h:719
ImSaturate
static float ImSaturate(float f)
Definition: imgui_internal.h:334
ImGuiTabBar::VisibleTabWasSubmitted
bool VisibleTabWasSubmitted
Definition: imgui_internal.h:1630
ImGuiPayload
Definition: imgui.h:1598
ImRect::Translate
void Translate(const ImVec2 &d)
Definition: imgui_internal.h:709
ImGuiSelectableFlags_SpanAllColumns
@ ImGuiSelectableFlags_SpanAllColumns
Definition: imgui.h:861
ImGui::BeginGroup
IMGUI_API void BeginGroup()
Definition: imgui.cpp:7179
enabled
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: glcorearb.h:4174
ImGui::BeginCombo
IMGUI_API bool BeginCombo(const char *label, const char *preview_value, ImGuiComboFlags flags=0)
Definition: imgui_widgets.cpp:1443
ImStb::STB_TEXTEDIT_DELETECHARS
static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING *obj, int pos, int n)
Definition: imgui_widgets.cpp:3220
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:7798
ImGuiWindow::SkipItems
bool SkipItems
Definition: imgui_internal.h:1483
ImDrawListSplitter::SetCurrentChannel
IMGUI_API void SetCurrentChannel(ImDrawList *draw_list, int channel_idx)
Definition: imgui_draw.cpp:1411
ImGui::DragScalarN
IMGUI_API bool DragScalarN(const char *label, ImGuiDataType data_type, void *p_data, int components, float v_speed, const void *p_min=NULL, const void *p_max=NULL, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:2160
ImGuiIO::MouseDown
bool MouseDown[5]
Definition: imgui.h:1486
ImGuiComboFlags_HeightRegular
@ ImGuiComboFlags_HeightRegular
Definition: imgui.h:873
ImGuiWindowFlags_AlwaysUseWindowPadding
@ ImGuiWindowFlags_AlwaysUseWindowPadding
Definition: imgui.h:785
ImGuiTreeNodeFlags_SpanAvailWidth
@ ImGuiTreeNodeFlags_SpanAvailWidth
Definition: imgui.h:849
ImGuiColumns::Flags
ImGuiColumnsFlags Flags
Definition: imgui_internal.h:858
ImGui::End
IMGUI_API void End()
Definition: imgui.cpp:6007
ImGui::IsClippedEx
IMGUI_API bool IsClippedEx(const ImRect &bb, ImGuiID id, bool clip_even_when_logged)
Definition: imgui.cpp:3140
ImCharIsBlankW
static bool ImCharIsBlankW(unsigned int c)
Definition: imgui_internal.h:248
ImGuiSeparatorFlags_SpanAllColumns
@ ImGuiSeparatorFlags_SpanAllColumns
Definition: imgui_internal.h:513
ImVec4::y
float y
Definition: imgui.h:223
ImGui::InputDouble
IMGUI_API bool InputDouble(const char *label, double *v, double step=0.0, double step_fast=0.0, const char *format="%.6f", ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:3095
ImDrawList::AddCircleFilled
IMGUI_API void AddCircleFilled(const ImVec2 &center, float radius, ImU32 col, int num_segments=12)
Definition: imgui_draw.cpp:1141
ImGuiStyle::ItemInnerSpacing
ImVec2 ItemInnerSpacing
Definition: imgui.h:1382
imstb_textedit.h
ImStb::STB_TEXTEDIT_NEWLINE
static ImWchar STB_TEXTEDIT_NEWLINE
Definition: imgui_widgets.cpp:3194
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:5976
obj
GLsizei GLsizei GLuint * obj
Definition: glcorearb.h:3066
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:1628
ImGuiInputTextState::SelectAll
void SelectAll()
Definition: imgui_internal.h:802
S
#define S(n, x)
Definition: sha1.c:50
ImRect::GetBR
ImVec2 GetBR() const
Definition: imgui_internal.h:701
ImGuiColumns::HostWorkRect
ImRect HostWorkRect
Definition: imgui_internal.h:868
ImGuiInputTextFlags_CallbackAlways
@ ImGuiInputTextFlags_CallbackAlways
Definition: imgui.h:818
GImGui
ImGuiContext * GImGui
Definition: imgui.cpp:975
ImS16
signed short ImS16
Definition: imgui.h:191
ImGuiInputTextCallback
int(* ImGuiInputTextCallback)(ImGuiInputTextCallbackData *data)
Definition: imgui.h:175
ImS64
signed long long ImS64
Definition: imgui.h:203
ImGuiColumnsFlags
int ImGuiColumnsFlags
Definition: imgui_internal.h:104
ImGuiWindowTempData::TextWrapPos
float TextWrapPos
Definition: imgui_internal.h:1412
IMGUI_TEST_ENGINE_ITEM_INFO
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID, _LABEL, _FLAGS)
Definition: imgui_internal.h:1935
ImGuiDataType_Double
@ ImGuiDataType_Double
Definition: imgui.h:969
ImGuiColumnData::OffsetNorm
float OffsetNorm
Definition: imgui_internal.h:847
ImGuiTabBar::Flags
ImGuiTabBarFlags Flags
Definition: imgui_internal.h:1626
ImGui::RenderColorRectWithAlphaCheckerboard
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList *draw_list, 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_draw.cpp:3337
GetTabBarFromTabBarRef
static ImGuiTabBar * GetTabBarFromTabBarRef(const ImGuiPtrOrIndex &ref)
Definition: imgui_widgets.cpp:6477
ImDrawCornerFlags
int ImDrawCornerFlags
Definition: imgui.h:152
ImGuiColorEditFlags_Uint8
@ ImGuiColorEditFlags_Uint8
Definition: imgui.h:1207
ImGuiTabItemFlags_NoCloseWithMiddleMouseButton
@ ImGuiTabItemFlags_NoCloseWithMiddleMouseButton
Definition: imgui.h:903
ImGui::GetWindowScrollbarID
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow *window, ImGuiAxis axis)
Definition: imgui_widgets.cpp:810
ImGuiInputTextState::CursorClamp
void CursorClamp()
Definition: imgui_internal.h:799
ImGui::ColorConvertHSVtoRGB
IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float &out_r, float &out_g, float &out_b)
Definition: imgui.cpp:1853
ImGuiIO::MouseClicked
bool MouseClicked[5]
Definition: imgui.h:1529
ImStb::STB_TEXTEDIT_LAYOUTROW
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow *r, STB_TEXTEDIT_STRING *obj, int line_start_idx)
Definition: imgui_widgets.cpp:3195
ImGuiTabBar::ImGuiTabBar
ImGuiTabBar()
Definition: imgui_widgets.cpp:6455
ImGuiWindow::Scroll
ImVec2 Scroll
Definition: imgui_internal.h:1472
IM_S32_MAX
static const ImS32 IM_S32_MAX
Definition: imgui_widgets.cpp:94
ImVector::Data
T * Data
Definition: imgui.h:1305
ImGuiButtonFlags_MouseButtonMiddle
@ ImGuiButtonFlags_MouseButtonMiddle
Definition: imgui_internal.h:458
IM_COL32_A_MASK
#define IM_COL32_A_MASK
Definition: imgui.h:1818
ImGuiButtonFlags_NoHoveredOnFocus
@ ImGuiButtonFlags_NoHoveredOnFocus
Definition: imgui_internal.h:455
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:1469
ImGui::SetItemAllowOverlap
IMGUI_API void SetItemAllowOverlap()
Definition: imgui.cpp:4659
ImGuiButtonFlags_Repeat
@ ImGuiButtonFlags_Repeat
Definition: imgui_internal.h:440
GetTabBarRefFromTabBar
static ImGuiPtrOrIndex GetTabBarRefFromTabBar(ImGuiTabBar *tab_bar)
Definition: imgui_widgets.cpp:6483
ImStrbolW
const ImWchar * ImStrbolW(const ImWchar *buf_mid_line, const ImWchar *buf_begin)
Definition: imgui.cpp:1367
IM_U64_MAX
static const ImU64 IM_U64_MAX
Definition: imgui_widgets.cpp:108
ImGuiWindowTempData::TreeDepth
int TreeDepth
Definition: imgui_internal.h:1398
ImGuiColorEditFlags_NoBorder
@ ImGuiColorEditFlags_NoBorder
Definition: imgui.h:1197
ImGuiCol_TabActive
@ ImGuiCol_TabActive
Definition: imgui.h:1121
ImGuiTabItem::NameOffset
int NameOffset
Definition: imgui_internal.h:1599
ImGui::DragBehavior
IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void *p_v, float v_speed, const void *p_min, const void *p_max, const char *format, float power, ImGuiDragFlags flags)
Definition: imgui_widgets.cpp:2053
Count
Count
ImGui::SetItemDefaultFocus
IMGUI_API void SetItemDefaultFocus()
Definition: imgui.cpp:6590
ImGuiButtonFlags_NoKeyModifiers
@ ImGuiButtonFlags_NoKeyModifiers
Definition: imgui_internal.h:452
ImGuiIO::ConfigMacOSXBehaviors
bool ConfigMacOSXBehaviors
Definition: imgui.h:1443
stride
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:3141
ImGuiNavDirSourceFlags_PadDPad
@ ImGuiNavDirSourceFlags_PadDPad
Definition: imgui_internal.h:629
border
GLint GLint GLsizei GLint border
Definition: glcorearb.h:2773
ImFont::Scale
float Scale
Definition: imgui.h:2292
prefix
static const char prefix[]
Definition: test_pair_ipc.cpp:26
ImGuiDataType
int ImGuiDataType
Definition: imgui.h:145
ImGuiMenuColumns::CalcExtraSpace
float CalcExtraSpace(float avail_w) const
Definition: imgui_widgets.cpp:6073
ImGuiWindowTempData::CursorMaxPos
ImVec2 CursorMaxPos
Definition: imgui_internal.h:1370
ImGuiTreeNodeFlags_None
@ ImGuiTreeNodeFlags_None
Definition: imgui.h:837
ImGuiColumnsFlags_NoForceWithinWindow
@ ImGuiColumnsFlags_NoForceWithinWindow
Definition: imgui_internal.h:486
ImGui::TreePushOverrideID
IMGUI_API void TreePushOverrideID(ImGuiID id)
Definition: imgui_widgets.cpp:5471
offset
GLintptr offset
Definition: glcorearb.h:2944
ImGuiColumnsFlags_NoResize
@ ImGuiColumnsFlags_NoResize
Definition: imgui_internal.h:484
ImGui::SetNavIDWithRectRel
IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect &rect_rel)
Definition: imgui.cpp:7919
ImGuiItemFlags
int ImGuiItemFlags
Definition: imgui_internal.h:106
ImGui::TabItemLabelAndCloseButton
IMGUI_API bool TabItemLabelAndCloseButton(ImDrawList *draw_list, const ImRect &bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char *label, ImGuiID tab_id, ImGuiID close_button_id)
Definition: imgui_widgets.cpp:7244
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:3141
ImVector::erase
T * erase(const T *it)
Definition: imgui.h:1346
ImGui::ButtonEx
IMGUI_API bool ButtonEx(const char *label, const ImVec2 &size_arg=ImVec2(0, 0), ImGuiButtonFlags flags=0)
Definition: imgui_widgets.cpp:638
ImGuiButtonFlags_PressedOnClickReleaseAnywhere
@ ImGuiButtonFlags_PressedOnClickReleaseAnywhere
Definition: imgui_internal.h:443
ImGuiStyleVar_WindowMinSize
@ ImGuiStyleVar_WindowMinSize
Definition: imgui.h:1157
ImGuiDataTypeInfo::ScanFmt
const char * ScanFmt
Definition: imgui_internal.h:723
ImGuiButtonFlags_PressedOnDragDropHold
@ ImGuiButtonFlags_PressedOnDragDropHold
Definition: imgui_internal.h:446
ImGui::GetColumnNormFromOffset
IMGUI_API float GetColumnNormFromOffset(const ImGuiColumns *columns, float offset)
Definition: imgui_widgets.cpp:7334
ImGuiSelectableFlags_AllowItemOverlap
@ ImGuiSelectableFlags_AllowItemOverlap
Definition: imgui.h:864
id
GLenum GLuint id
Definition: glcorearb.h:2695
ImGuiInputTextState::HasSelection
bool HasSelection() const
Definition: imgui_internal.h:800
ImGui::GetContentRegionMaxAbs
IMGUI_API ImVec2 GetContentRegionMaxAbs()
Definition: imgui.cpp:7143
ImGuiTabItem::Width
float Width
Definition: imgui_internal.h:1601
ImGui::TreeNodeEx
IMGUI_API bool TreeNodeEx(const char *label, ImGuiTreeNodeFlags flags=0)
Definition: imgui_widgets.cpp:5166
ImGuiKey_Y
@ ImGuiKey_Y
Definition: imgui.h:1007
ImGuiKey_DownArrow
@ ImGuiKey_DownArrow
Definition: imgui.h:991
ImGuiColorEditFlags_AlphaBar
@ ImGuiColorEditFlags_AlphaBar
Definition: imgui.h:1200
RenderArrowsForVerticalBar
static void RenderArrowsForVerticalBar(ImDrawList *draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha)
Definition: imgui_widgets.cpp:4497
ImGuiTabBar::ScrollingSpeed
float ScrollingSpeed
Definition: imgui_internal.h:1625
format
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:2773
ImGuiContext::NextItemData
ImGuiNextItemData NextItemData
Definition: imgui_internal.h:1081
ImGuiInputTextFlags_ReadOnly
@ ImGuiInputTextFlags_ReadOnly
Definition: imgui.h:824
ImGui::Columns
IMGUI_API void Columns(int count=1, const char *id=NULL, bool border=true)
Definition: imgui_widgets.cpp:7697
ImGui::SetFocusID
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow *window)
Definition: imgui.cpp:7929
ImGuiWindow::DrawList
ImDrawList * DrawList
Definition: imgui_internal.h:1525
ImParseFormatPrecision
int ImParseFormatPrecision(const char *fmt, int default_precision)
Definition: imgui_widgets.cpp:2842
ImGuiItemHoveredDataBackup::Restore
void Restore() const
Definition: imgui_internal.h:1571
update_failure_list.str
str
Definition: update_failure_list.py:41
ImGuiButtonFlags_PressedOnClickRelease
@ ImGuiButtonFlags_PressedOnClickRelease
Definition: imgui_internal.h:442
ImVector::Size
int Size
Definition: imgui.h:1303
ImStrncpy
void ImStrncpy(char *dst, const char *src, size_t count)
Definition: imgui.cpp:1316
ImVec2::x
float x
Definition: imgui.h:210
IM_S16_MIN
static const signed short IM_S16_MIN
Definition: imgui_widgets.cpp:89
ImGuiTabBar::OffsetMax
float OffsetMax
Definition: imgui_internal.h:1619
ImGui::ItemAdd
IMGUI_API bool ItemAdd(const ImRect &bb, ImGuiID id, const ImRect *nav_bb=NULL)
Definition: imgui.cpp:6864
ImParseFormatFindStart
const char * ImParseFormatFindStart(const char *fmt)
Definition: imgui_widgets.cpp:2793
ImGuiColumns::ID
ImGuiID ID
Definition: imgui_internal.h:857
ImGuiStyle
Definition: imgui.h:1365
ImGuiInputTextCallbackData::UserData
void * UserData
Definition: imgui.h:1564
ImGuiDir_Up
@ ImGuiDir_Up
Definition: imgui.h:979
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:1270
ImGuiDataType_U32
@ ImGuiDataType_U32
Definition: imgui.h:965
ImGuiSelectableFlags_SelectOnRelease
@ ImGuiSelectableFlags_SelectOnRelease
Definition: imgui_internal.h:496
ImGuiDragDropFlags_SourceNoDisableHover
@ ImGuiDragDropFlags_SourceNoDisableHover
Definition: imgui.h:941
ImGui::GetWindowAllowedExtentRect
IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow *window)
Definition: imgui.cpp:7851
ImGuiItemStatusFlags_ToggledSelection
@ ImGuiItemStatusFlags_ToggledSelection
Definition: imgui_internal.h:538
ImGui::PopItemFlag
IMGUI_API void PopItemFlag()
Definition: imgui.cpp:6194
ImVector::push_back
void push_back(const T &v)
Definition: imgui.h:1343
ImGuiCol_SeparatorActive
@ ImGuiCol_SeparatorActive
Definition: imgui.h:1115
ImGuiTabBar::ReorderRequestDir
ImS8 ReorderRequestDir
Definition: imgui_internal.h:1628
ImGuiIO::MouseDelta
ImVec2 MouseDelta
Definition: imgui.h:1519
ImGuiTreeNodeFlags_FramePadding
@ ImGuiTreeNodeFlags_FramePadding
Definition: imgui.h:848
ImGuiWindow::ScrollbarSizes
ImVec2 ScrollbarSizes
Definition: imgui_internal.h:1476
ImGuiKey_KeyPadEnter
@ ImGuiKey_KeyPadEnter
Definition: imgui.h:1002
IM_U64_MIN
static const ImU64 IM_U64_MIN
Definition: imgui_widgets.cpp:104
ImGui::TextDisabled
IMGUI_API void TextDisabled(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui_widgets.cpp:281
ImGui::LogRenderedText
IMGUI_API void LogRenderedText(const ImVec2 *ref_pos, const char *text, const char *text_end=NULL)
Definition: imgui.cpp:9333
ImGuiCol_ChildBg
@ ImGuiCol_ChildBg
Definition: imgui.h:1089
ImGuiWindowTempData::NavLayerCurrentMask
int NavLayerCurrentMask
Definition: imgui_internal.h:1387
ImGuiInputTextCallbackData::BufDirty
bool BufDirty
Definition: imgui.h:1574
testing::internal::fmt
GTEST_API_ const char * fmt
Definition: gtest.h:1835
ImGui::PushID
IMGUI_API void PushID(const char *str_id)
Definition: imgui.cpp:6619
ImGuiSelectableFlags_DontClosePopups
@ ImGuiSelectableFlags_DontClosePopups
Definition: imgui.h:860
ImGui::CalcItemWidth
IMGUI_API float CalcItemWidth()
Definition: imgui.cpp:7062
ImGui::RenderArrow
IMGUI_API void RenderArrow(ImDrawList *draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale=1.0f)
Definition: imgui_draw.cpp:3179
ImGuiLayoutType_Vertical
@ ImGuiLayoutType_Vertical
Definition: imgui_internal.h:569
ImGui::InputFloat4
IMGUI_API bool InputFloat4(const char *label, float v[4], const char *format="%.3f", ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:3033
p
const char * p
Definition: gmock-matchers_test.cc:3863
ImGui::SetTooltip
IMGUI_API void SetTooltip(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui.cpp:7485
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:2652
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:2245
ImGuiStorage::GetInt
IMGUI_API int GetInt(ImGuiID key, int default_val=0) const
Definition: imgui.cpp:1925
ImGuiInputTextFlags_EnterReturnsTrue
@ ImGuiInputTextFlags_EnterReturnsTrue
Definition: imgui.h:815
Items_ArrayGetter
static bool Items_ArrayGetter(void *data, int idx, const char **out_text)
Definition: imgui_widgets.cpp:1557
ImGui::TreePop
IMGUI_API void TreePop()
Definition: imgui_widgets.cpp:5479
ImGuiCol_Text
@ ImGuiCol_Text
Definition: imgui.h:1086
ImGui::GetNavInputAmount2d
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor=0.0f, float fast_factor=0.0f)
Definition: imgui.cpp:8355
IM_S64_MAX
static const ImS64 IM_S64_MAX
Definition: imgui_widgets.cpp:102
ImGuiTabBarFlags_IsFocused
@ ImGuiTabBarFlags_IsFocused
Definition: imgui_internal.h:1582
ImGuiNavForward_None
@ ImGuiNavForward_None
Definition: imgui_internal.h:647
ImDrawList::AddTriangle
IMGUI_API void AddTriangle(const ImVec2 &p1, const ImVec2 &p2, const ImVec2 &p3, ImU32 col, float thickness=1.0f)
Definition: imgui_draw.cpp:1089
ImGuiTabBar::ScrollingTarget
float ScrollingTarget
Definition: imgui_internal.h:1623
IM_ROUND
#define IM_ROUND(_VAL)
Definition: imgui_internal.h:186
ImGui::EndGroup
IMGUI_API void EndGroup()
Definition: imgui.cpp:7204
IM_ALLOC
#define IM_ALLOC(_SIZE)
Definition: imgui.h:1283
ImGui::OpenPopupOnItemClick
IMGUI_API bool OpenPopupOnItemClick(const char *str_id=NULL, ImGuiMouseButton mouse_button=1)
Definition: imgui.cpp:7747
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:2662
ImGui::BeginTabItem
IMGUI_API bool BeginTabItem(const char *label, bool *p_open=NULL, ImGuiTabItemFlags flags=0)
Definition: imgui_widgets.cpp:6951
size
#define size
Definition: glcorearb.h:2944
ImGuiWindowTempData::LayoutType
ImGuiLayoutType LayoutType
Definition: imgui_internal.h:1403
ImLinearSweep
static float ImLinearSweep(float current, float target, float speed)
Definition: imgui_internal.h:343
ImGuiButtonFlags_MouseButtonDefault_
@ ImGuiButtonFlags_MouseButtonDefault_
Definition: imgui_internal.h:462
ImGuiColumns::OffMaxX
float OffMaxX
Definition: imgui_internal.h:863
ImGui::PopID
IMGUI_API void PopID()
Definition: imgui.cpp:6650
ImGuiCol_ButtonHovered
@ ImGuiCol_ButtonHovered
Definition: imgui.h:1108
ImGui::InputScalarN
IMGUI_API bool InputScalarN(const char *label, ImGuiDataType data_type, void *p_data, int components, const void *p_step=NULL, const void *p_step_fast=NULL, const char *format=NULL, ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2982
ImTextCountCharsFromUtf8
int ImTextCountCharsFromUtf8(const char *in_text, const char *in_text_end)
Definition: imgui.cpp:1699
ImGuiColorEditFlags_DisplayHSV
@ ImGuiColorEditFlags_DisplayHSV
Definition: imgui.h:1205
ImGuiKey_LeftArrow
@ ImGuiKey_LeftArrow
Definition: imgui.h:988
ImGuiTabBar::OffsetMaxIdeal
float OffsetMaxIdeal
Definition: imgui_internal.h:1620
ImGui::InputTextEx
IMGUI_API bool InputTextEx(const char *label, const char *hint, char *buf, int buf_size, const ImVec2 &size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback=NULL, void *user_data=NULL)
Definition: imgui_widgets.cpp:3448
ImGui::Spacing
IMGUI_API void Spacing()
Definition: imgui_widgets.cpp:1207
CalcMaxPopupHeightFromItemCount
static float CalcMaxPopupHeightFromItemCount(int items_count)
Definition: imgui_widgets.cpp:1435
ImGuiInputSource_NavKeyboard
@ ImGuiInputSource_NavKeyboard
Definition: imgui_internal.h:600
IM_ARRAYSIZE
#define IM_ARRAYSIZE(_ARR)
Definition: imgui.h:88
STB_TEXTEDIT_K_LINESTART
#define STB_TEXTEDIT_K_LINESTART
Definition: imgui_widgets.cpp:3271
ImGuiCol_TabUnfocused
@ ImGuiCol_TabUnfocused
Definition: imgui.h:1122
ImGui::TreeNode
IMGUI_API bool TreeNode(const char *label)
Definition: imgui_widgets.cpp:5148
ImGuiDataType_COUNT
@ ImGuiDataType_COUNT
Definition: imgui.h:970
ImGui::SetHoveredID
IMGUI_API void SetHoveredID(ImGuiID id)
Definition: imgui.cpp:3006
ImGui::BeginPopupEx
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
Definition: imgui.cpp:7664
ImGui::BeginDragDropTarget
IMGUI_API bool BeginDragDropTarget()
Definition: imgui.cpp:9212
ImGuiInputTextFlags_AutoSelectAll
@ ImGuiInputTextFlags_AutoSelectAll
Definition: imgui.h:814
ImGuiColumns::Current
int Current
Definition: imgui_internal.h:861
ImGuiTabBar::GetTabOrder
int GetTabOrder(const ImGuiTabItem *tab) const
Definition: imgui_internal.h:1636
ImGuiTreeNodeFlags_AllowItemOverlap
@ ImGuiTreeNodeFlags_AllowItemOverlap
Definition: imgui.h:840
ImGuiColorEditFlags_PickerHueBar
@ ImGuiColorEditFlags_PickerHueBar
Definition: imgui.h:1209
ImGuiColumnsFlags_GrowParentContentsSize
@ ImGuiColumnsFlags_GrowParentContentsSize
Definition: imgui_internal.h:487
ImStb::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:3235
ImGui::InputInt4
IMGUI_API bool InputInt4(const char *label, int v[4], ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:3090
STB_TEXTEDIT_K_DELETE
#define STB_TEXTEDIT_K_DELETE
Definition: imgui_widgets.cpp:3275
GetDraggedColumnOffset
static float GetDraggedColumnOffset(ImGuiColumns *columns, int column_index)
Definition: imgui_widgets.cpp:7341
ImGuiTextBuffer::append
IMGUI_API void append(const char *str, const char *str_end=NULL)
Definition: imgui.cpp:2147
ImVector::reserve
void reserve(int new_capacity)
Definition: imgui.h:1340
ULL
#define ULL(x)
Definition: coded_stream_unittest.cc:57
ImGui::FindRenderedTextEnd
const IMGUI_API char * FindRenderedTextEnd(const char *text, const char *text_end=NULL)
Definition: imgui.cpp:2561
ImGui::InputTextWithHint
IMGUI_API bool InputTextWithHint(const char *label, const char *hint, char *buf, size_t buf_size, ImGuiInputTextFlags flags=0, ImGuiInputTextCallback callback=NULL, void *user_data=NULL)
Definition: imgui_widgets.cpp:3121
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:2210
ImGuiCol_PlotHistogramHovered
@ ImGuiCol_PlotHistogramHovered
Definition: imgui.h:1127
ImRect
Definition: imgui_internal.h:684
ImGuiButtonFlags_AllowItemOverlap
@ ImGuiButtonFlags_AllowItemOverlap
Definition: imgui_internal.h:448
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:2766
IM_U16_MIN
static const unsigned short IM_U16_MIN
Definition: imgui_widgets.cpp:91
ImGui::SetActiveID
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow *window)
Definition: imgui.cpp:2969
ImGuiColorEditFlags_AlphaPreviewHalf
@ ImGuiColorEditFlags_AlphaPreviewHalf
Definition: imgui.h:1202
ImGui::MenuItem
IMGUI_API bool MenuItem(const char *label, const char *shortcut=NULL, bool selected=false, bool enabled=true)
Definition: imgui_widgets.cpp:6365
ImGuiContext::ColorEditOptions
ImGuiColorEditFlags ColorEditOptions
Definition: imgui_internal.h:1180
IM_U32_MIN
static const ImU32 IM_U32_MIN
Definition: imgui_widgets.cpp:95
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:2692
ImGui::DataTypeGetInfo
const IMGUI_API ImGuiDataTypeInfo * DataTypeGetInfo(ImGuiDataType data_type)
Definition: imgui_widgets.cpp:1704
ImGui::TempInputScalar
IMGUI_API bool TempInputScalar(const ImRect &bb, ImGuiID id, const char *label, ImGuiDataType data_type, void *p_data, const char *format)
Definition: imgui_widgets.cpp:2886
d
d
ImGuiCol_Border
@ ImGuiCol_Border
Definition: imgui.h:1091
ImGuiTabItem::LastFrameSelected
int LastFrameSelected
Definition: imgui_internal.h:1598
ImGui::IsKeyPressedMap
bool IsKeyPressedMap(ImGuiKey key, bool repeat=true)
Definition: imgui_internal.h:1777
ImGuiSelectableFlags_Disabled
@ ImGuiSelectableFlags_Disabled
Definition: imgui.h:863
ImGuiCol_ButtonActive
@ ImGuiCol_ButtonActive
Definition: imgui.h:1109
ImGui::SetColumnWidth
IMGUI_API void SetColumnWidth(int column_index, float width)
Definition: imgui_widgets.cpp:7422
ImGui::TabBarCloseTab
IMGUI_API void TabBarCloseTab(ImGuiTabBar *tab_bar, ImGuiTabItem *tab)
Definition: imgui_widgets.cpp:6800
ImGuiInputTextCallbackData::EventChar
ImWchar EventChar
Definition: imgui.h:1569
ImGuiStyleVar_FramePadding
@ ImGuiStyleVar_FramePadding
Definition: imgui.h:1163
ImGuiItemStatusFlags_HoveredRect
@ ImGuiItemStatusFlags_HoveredRect
Definition: imgui_internal.h:535
ImGui::TabBarScrollToTab
static void TabBarScrollToTab(ImGuiTabBar *tab_bar, ImGuiTabItem *tab)
Definition: imgui_widgets.cpp:6822
ImGui::Checkbox
IMGUI_API bool Checkbox(const char *label, bool *v)
Definition: imgui_widgets.cpp:1008
ImGuiWindow::NavRectRel
ImRect NavRectRel[ImGuiNavLayer_COUNT]
Definition: imgui_internal.h:1534
ImGui::AcceptDragDropPayload
const IMGUI_API ImGuiPayload * AcceptDragDropPayload(const char *type, ImGuiDragDropFlags flags=0)
Definition: imgui.cpp:9244
ImGuiWindowFlags_ChildWindow
@ ImGuiWindowFlags_ChildWindow
Definition: imgui.h:795
precision
GLenum GLint GLint * precision
Definition: glcorearb.h:3963
ImGuiNavForward_ForwardQueued
@ ImGuiNavForward_ForwardQueued
Definition: imgui_internal.h:648
ImRect::GetWidth
float GetWidth() const
Definition: imgui_internal.h:696
ImGui::InputFloat2
IMGUI_API bool InputFloat2(const char *label, float v[2], const char *format="%.3f", ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:3023
ImGui::TreeNodeBehaviorIsOpen
IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags=0)
Definition: imgui_widgets.cpp:5215
ImGui::TextWrappedV
IMGUI_API void TextWrappedV(const char *fmt, va_list args) IM_FMTLIST(1)
Definition: imgui_widgets.cpp:304
ImDrawCornerFlags_BotLeft
@ ImDrawCornerFlags_BotLeft
Definition: imgui.h:1936
ImGui::IsMousePosValid
IMGUI_API bool IsMousePosValid(const ImVec2 *mouse_pos=NULL)
Definition: imgui.cpp:4500
ImGui::DragScalar
IMGUI_API bool DragScalar(const char *label, ImGuiDataType data_type, void *p_data, float v_speed, const void *p_min=NULL, const void *p_max=NULL, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:2086
ImGuiDir_Left
@ ImGuiDir_Left
Definition: imgui.h:977
ImGui::VSliderScalar
IMGUI_API bool VSliderScalar(const char *label, const ImVec2 &size, ImGuiDataType data_type, void *p_data, const void *p_min, const void *p_max, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:2702
ImGui::StartMouseMovingWindow
IMGUI_API void StartMouseMovingWindow(ImGuiWindow *window)
Definition: imgui.cpp:3324
ImVec4::x
float x
Definition: imgui.h:223
ImGuiCol_PlotLines
@ ImGuiCol_PlotLines
Definition: imgui.h:1124
ImGuiInputReadMode_Pressed
@ ImGuiInputReadMode_Pressed
Definition: imgui_internal.h:609
ImGuiTreeNodeFlags_Leaf
@ ImGuiTreeNodeFlags_Leaf
Definition: imgui.h:846
ImMax
static T ImMax(T lhs, T rhs)
Definition: imgui_internal.h:321
ImGuiCol_TabHovered
@ ImGuiCol_TabHovered
Definition: imgui.h:1120
buf
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:4175
key
const SETUP_TEARDOWN_TESTCONTEXT char * key
Definition: test_wss_transport.cpp:10
ImGuiColumns::HostCursorMaxPosX
float HostCursorMaxPosX
Definition: imgui_internal.h:866
ImGuiInputTextState::TextA
ImVector< char > TextA
Definition: imgui_internal.h:777
ImGuiContext
Definition: imgui_internal.h:1018
ImU32
unsigned int ImU32
Definition: imgui.h:194
ImRect::Contains
bool Contains(const ImVec2 &p) const
Definition: imgui_internal.h:702
ImGui::FocusableItemUnregister
IMGUI_API void FocusableItemUnregister(ImGuiWindow *window)
Definition: imgui.cpp:3189
ImGuiCol_TabUnfocusedActive
@ ImGuiCol_TabUnfocusedActive
Definition: imgui.h:1123
ImGuiSelectableFlags_AllowDoubleClick
@ ImGuiSelectableFlags_AllowDoubleClick
Definition: imgui.h:862
ImU8
unsigned char ImU8
Definition: imgui.h:190
ImGui::SetNextWindowSize
IMGUI_API void SetNextWindowSize(const ImVec2 &size, ImGuiCond cond=0)
Definition: imgui.cpp:6480
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:3273
ImGuiInputTextFlags_NoUndoRedo
@ ImGuiInputTextFlags_NoUndoRedo
Definition: imgui.h:826
ImGuiDataType_U64
@ ImGuiDataType_U64
Definition: imgui.h:967
ImGuiWindow::ClipRect
ImRect ClipRect
Definition: imgui_internal.h:1514
TabItemComparerByVisibleOffset
static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void *lhs, const void *rhs)
Definition: imgui_widgets.cpp:6470
ImGui::SetCursorScreenPos
IMGUI_API void SetCursorScreenPos(const ImVec2 &pos)
Definition: imgui.cpp:6952
ImGui::Value
IMGUI_API void Value(const char *prefix, bool b)
Definition: imgui_widgets.cpp:5994
ImGuiCol_ScrollbarGrabActive
@ ImGuiCol_ScrollbarGrabActive
Definition: imgui.h:1103
ImRect::GetBL
ImVec2 GetBL() const
Definition: imgui_internal.h:700
ImGuiWindow::Pos
ImVec2 Pos
Definition: imgui_internal.h:1461
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:2697
ImGuiSeparatorFlags_Horizontal
@ ImGuiSeparatorFlags_Horizontal
Definition: imgui_internal.h:511
ImGui::GetContentRegionAvail
IMGUI_API ImVec2 GetContentRegionAvail()
Definition: imgui.cpp:7153
ImGuiWindow::InnerRect
ImRect InnerRect
Definition: imgui_internal.h:1511
STB_TEXTEDIT_STRING
#define STB_TEXTEDIT_STRING
Definition: imgui_internal.h:127
ImGuiTreeNodeFlags_NoAutoOpenOnLog
@ ImGuiTreeNodeFlags_NoAutoOpenOnLog
Definition: imgui.h:842
STB_TexteditState
Definition: imstb_textedit.h:319
layer
GLenum GLuint GLint GLint layer
Definition: glcorearb.h:3469
ImStb::STB_TEXTEDIT_KEYTOTEXT
static int STB_TEXTEDIT_KEYTOTEXT(int key)
Definition: imgui_widgets.cpp:3193
ImGuiTreeNodeFlags_NoTreePushOnOpen
@ ImGuiTreeNodeFlags_NoTreePushOnOpen
Definition: imgui.h:841
ImGui::GetForegroundDrawList
IMGUI_API ImDrawList * GetForegroundDrawList()
Definition: imgui.cpp:3314
ImDrawList::AddLine
IMGUI_API void AddLine(const ImVec2 &p1, const ImVec2 &p2, ImU32 col, float thickness=1.0f)
Definition: imgui_draw.cpp:1011
ImGuiInputTextCallbackData::Flags
ImGuiInputTextFlags Flags
Definition: imgui.h:1563
ImGui::ColorConvertFloat4ToU32
IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4 &in)
Definition: imgui.cpp:1819
ImGuiComboFlags_None
@ ImGuiComboFlags_None
Definition: imgui.h:870
ImGuiKey_PageDown
@ ImGuiKey_PageDown
Definition: imgui.h:993
n
GLdouble n
Definition: glcorearb.h:4153
ImDrawList::PrimVtx
void PrimVtx(const ImVec2 &pos, const ImVec2 &uv, ImU32 col)
Definition: imgui.h:2060
ImGuiTabItemFlags_NoPushId
@ ImGuiTabItemFlags_NoPushId
Definition: imgui.h:904
ImGui::RenderFrameBorder
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding=0.0f)
Definition: imgui.cpp:2756
IM_S8_MAX
static const signed char IM_S8_MAX
Definition: imgui_widgets.cpp:86
ImGuiKey_C
@ ImGuiKey_C
Definition: imgui.h:1004
ImGuiLayoutType
int ImGuiLayoutType
Definition: imgui_internal.h:99
ImGuiInputTextState::TextW
ImVector< ImWchar > TextW
Definition: imgui_internal.h:776
ImGuiPlotArrayGetterData::Values
const float * Values
Definition: imgui_widgets.cpp:5952
ImGuiStyleVar_WindowRounding
@ ImGuiStyleVar_WindowRounding
Definition: imgui.h:1155
ImGuiColumns::HostCursorPosY
float HostCursorPosY
Definition: imgui_internal.h:865
ImGuiWindow::DC
ImGuiWindowTempData DC
Definition: imgui_internal.h:1506
LL
#define LL(x)
ImGuiColorEditFlags__PickerMask
@ ImGuiColorEditFlags__PickerMask
Definition: imgui.h:1221
ImDrawList::VtxBuffer
ImVector< ImDrawVert > VtxBuffer
Definition: imgui.h:1966
i
int i
Definition: gmock-matchers_test.cc:764
STB_TEXTEDIT_K_TEXTSTART
#define STB_TEXTEDIT_K_TEXTSTART
Definition: imgui_widgets.cpp:3273
IM_F32_TO_INT8_UNBOUND
#define IM_F32_TO_INT8_UNBOUND(_VAL)
Definition: imgui_internal.h:183
ImGui::PopStyleVar
IMGUI_API void PopStyleVar(int count=1)
Definition: imgui.cpp:2480
ImGui::SetNextItemOpen
IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond=0)
Definition: imgui_widgets.cpp:5509
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 frame_size)
Definition: imgui_widgets.cpp:5836
ImGui::ColorEditOptionsPopup
IMGUI_API void ColorEditOptionsPopup(const float *col, ImGuiColorEditFlags flags)
Definition: imgui_widgets.cpp:5026
ImGuiAxis
ImGuiAxis
Definition: imgui_internal.h:582
ImGuiPlotType_Lines
@ ImGuiPlotType_Lines
Definition: imgui_internal.h:591
ImGuiWindow
Definition: imgui_internal.h:1456
ImFormatStringV
int ImFormatStringV(char *buf, size_t buf_size, const char *fmt, va_list args)
Definition: imgui.cpp:1455
ImGui::CollapsingHeader
IMGUI_API bool CollapsingHeader(const char *label, ImGuiTreeNodeFlags flags=0)
Definition: imgui_widgets.cpp:5521
ImRect::GetTL
ImVec2 GetTL() const
Definition: imgui_internal.h:698
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:3073
ImGui::InputFloat3
IMGUI_API bool InputFloat3(const char *label, float v[3], const char *format="%.3f", ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:3028
ImGui::EndMainMenuBar
IMGUI_API void EndMainMenuBar()
Definition: imgui_widgets.cpp:6172
ImGuiItemFlags_NoNav
@ ImGuiItemFlags_NoNav
Definition: imgui_internal.h:524
ImGui::TreeNodeBehavior
IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char *label, const char *label_end=NULL)
Definition: imgui_widgets.cpp:5261
ImGuiKey_Escape
@ ImGuiKey_Escape
Definition: imgui.h:1001
ImGuiStyle::GrabMinSize
float GrabMinSize
Definition: imgui.h:1388
ImAtoi
static const char * ImAtoi(const char *src, TYPE *output)
Definition: imgui_widgets.cpp:1895
ImGuiTreeNodeFlags_ClipLabelForTrailingButton
@ ImGuiTreeNodeFlags_ClipLabelForTrailingButton
Definition: imgui_internal.h:505
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:4274
ImGuiTabBar::WantLayout
bool WantLayout
Definition: imgui_internal.h:1629
ImGui::TextWrapped
IMGUI_API void TextWrapped(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui_widgets.cpp:296
ImGuiColumnData::ClipRect
ImRect ClipRect
Definition: imgui_internal.h:850
ImGuiWindowTempData::MenuBarOffset
ImVec2 MenuBarOffset
Definition: imgui_internal.h:1396
ImGui::Scrollbar
IMGUI_API void Scrollbar(ImGuiAxis axis)
Definition: imgui_widgets.cpp:912
ImGui::IsMouseClicked
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat=false)
Definition: imgui.cpp:4433
ImRect::GetCenter
ImVec2 GetCenter() const
Definition: imgui_internal.h:694
ImGui::ArrowButton
IMGUI_API bool ArrowButton(const char *str_id, ImGuiDir dir)
Definition: imgui_widgets.cpp:748
ImGui::TextV
IMGUI_API void TextV(const char *fmt, va_list args) IM_FMTLIST(1)
Definition: imgui_widgets.cpp:255
ImGuiWindowTempData::FocusCounterRegular
int FocusCounterRegular
Definition: imgui_internal.h:1405
IM_FLOOR
#define IM_FLOOR(_VAL)
Definition: imgui_internal.h:185
ImGui::RenderCheckMark
IMGUI_API void RenderCheckMark(ImDrawList *draw_list, ImVec2 pos, ImU32 col, float sz)
Definition: imgui_draw.cpp:3215
ImGuiWindow::WorkRect
ImRect WorkRect
Definition: imgui_internal.h:1513
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:4889
ImGuiStyle::GrabRounding
float GrabRounding
Definition: imgui.h:1389
v1
GLfloat GLfloat v1
Definition: glcorearb.h:3086
ImGuiIO::InputQueueCharacters
ImVector< ImWchar > InputQueueCharacters
Definition: imgui.h:1543
ImGui::MarkIniSettingsDirty
IMGUI_API void MarkIniSettingsDirty()
Definition: imgui.cpp:9548
ImGui::IsMouseReleased
IMGUI_API bool IsMouseReleased(ImGuiMouseButton button)
Definition: imgui.cpp:4451
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:3110
ImGui::EndTooltip
IMGUI_API void EndTooltip()
Definition: imgui.cpp:7472
ImGuiCond_Always
@ ImGuiCond_Always
Definition: imgui.h:1267
ImGui::RenderBullet
IMGUI_API void RenderBullet(ImDrawList *draw_list, ImVec2 pos, ImU32 col)
Definition: imgui_draw.cpp:3210
ImGui::SliderScalarN
IMGUI_API bool SliderScalarN(const char *label, ImGuiDataType data_type, void *p_data, int components, const void *p_min, const void *p_max, const char *format=NULL, float power=1.0f)
Definition: imgui_widgets.cpp:2617
InputTextCalcTextLenAndLineCount
static int InputTextCalcTextLenAndLineCount(const char *text_begin, const char **out_text_end)
Definition: imgui_widgets.cpp:3127
ImFont::GetCharAdvance
float GetCharAdvance(ImWchar c) const
Definition: imgui.h:2302
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:2240
ImGuiIO::MousePos
ImVec2 MousePos
Definition: imgui.h:1485
ImDrawList::PathArcTo
IMGUI_API void PathArcTo(const ImVec2 &center, float radius, float a_min, float a_max, int num_segments=10)
Definition: imgui_draw.cpp:917
ImGuiShrinkWidthItem
Definition: imgui_internal.h:999
ImGui::PopClipRect
IMGUI_API void PopClipRect()
Definition: imgui.cpp:4135
ImGuiInputTextCallbackData::InsertChars
IMGUI_API void InsertChars(int pos, const char *text, const char *text_end=NULL)
Definition: imgui_widgets.cpp:3338
ImGuiWindow::ContentSize
ImVec2 ContentSize
Definition: imgui_internal.h:1464
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:2618
ImGuiInputTextFlags_CallbackCharFilter
@ ImGuiInputTextFlags_CallbackCharFilter
Definition: imgui.h:819
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem
@ ImGuiHoveredFlags_AllowWhenBlockedByActiveItem
Definition: imgui.h:928
ImGuiItemFlags_MixedValue
@ ImGuiItemFlags_MixedValue
Definition: imgui_internal.h:527
ImGui::AlignTextToFramePadding
IMGUI_API void AlignTextToFramePadding()
Definition: imgui_widgets.cpp:1242
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:2743
ImGuiDir_Down
@ ImGuiDir_Down
Definition: imgui.h:980
ImGuiTreeNodeFlags_OpenOnDoubleClick
@ ImGuiTreeNodeFlags_OpenOnDoubleClick
Definition: imgui.h:844
ImGui::Indent
IMGUI_API void Indent(float indent_w=0.0f)
Definition: imgui.cpp:7006
ImGui::ColorEdit3
IMGUI_API bool ColorEdit3(const char *label, float col[3], ImGuiColorEditFlags flags=0)
Definition: imgui_widgets.cpp:4242
ImGuiTabBarFlags_FittingPolicyMask_
@ ImGuiTabBarFlags_FittingPolicyMask_
Definition: imgui.h:893
len
int len
Definition: php/ext/google/protobuf/map.c:206
ImGui::ColorTooltip
IMGUI_API void ColorTooltip(const char *text, const float *col, ImGuiColorEditFlags flags)
Definition: imgui_widgets.cpp:4992
ImGui::TextUnformatted
IMGUI_API void TextUnformatted(const char *text, const char *text_end=NULL)
Definition: imgui_widgets.cpp:242
ImGuiColorEditFlags_NoAlpha
@ ImGuiColorEditFlags_NoAlpha
Definition: imgui.h:1188
ImGuiDataType_S64
@ ImGuiDataType_S64
Definition: imgui.h:966
ImGuiNavHighlightFlags_TypeThin
@ ImGuiNavHighlightFlags_TypeThin
Definition: imgui_internal.h:620
ImGui::TabBarScrollingButtons
static ImGuiTabItem * TabBarScrollingButtons(ImGuiTabBar *tab_bar)
Definition: imgui_widgets.cpp:6850
v
const GLdouble * v
Definition: glcorearb.h:3106
ImGuiTreeNodeFlags_SpanFullWidth
@ ImGuiTreeNodeFlags_SpanFullWidth
Definition: imgui.h:850
ImGuiColumns::Count
int Count
Definition: imgui_internal.h:862
ImGui::TempInputIsActive
bool TempInputIsActive(ImGuiID id)
Definition: imgui_internal.h:1876
STB_TEXTEDIT_K_UP
#define STB_TEXTEDIT_K_UP
Definition: imgui_widgets.cpp:3269
ImGui::Bullet
IMGUI_API void Bullet()
Definition: imgui_widgets.cpp:1171
ImGuiTabBar::ReorderRequestTabId
ImGuiID ReorderRequestTabId
Definition: imgui_internal.h:1627
ImGuiSelectableFlags
int ImGuiSelectableFlags
Definition: imgui.h:164
ImGuiWindow::MoveId
ImGuiID MoveId
Definition: imgui_internal.h:1470
ImGuiInputTextCallbackData::DeleteChars
IMGUI_API void DeleteChars(int pos, int bytes_count)
Definition: imgui_widgets.cpp:3320
ImGuiColorEditFlags_NoLabel
@ ImGuiColorEditFlags_NoLabel
Definition: imgui.h:1194
ImGuiStyle::ScrollbarRounding
float ScrollbarRounding
Definition: imgui.h:1387
ImGuiIO::MouseDoubleClicked
bool MouseDoubleClicked[5]
Definition: imgui.h:1530
ImGuiTabBarFlags_Reorderable
@ ImGuiTabBarFlags_Reorderable
Definition: imgui.h:885
ImGui::ShrinkWidths
IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem *items, int count, float width_excess)
Definition: imgui_widgets.cpp:1392
ImGuiTreeNodeFlags_Selected
@ ImGuiTreeNodeFlags_Selected
Definition: imgui.h:838
ImGuiInputTextState::ClearSelection
void ClearSelection()
Definition: imgui_internal.h:801
ImGui::SetDragDropPayload
IMGUI_API bool SetDragDropPayload(const char *type, const void *data, size_t sz, ImGuiCond cond=0)
Definition: imgui.cpp:9143
ImGui::PopItemWidth
IMGUI_API void PopItemWidth()
Definition: imgui.cpp:7053
ImGuiWindow::WindowBorderSize
float WindowBorderSize
Definition: imgui_internal.h:1468
ImGui::SliderBehaviorT
IMGUI_API bool SliderBehaviorT(const ImRect &bb, ImGuiID id, ImGuiDataType data_type, T *v, T v_min, T v_max, const char *format, float power, ImGuiSliderFlags flags, ImRect *out_grab_bb)
ImGuiNavHighlightFlags_NoRounding
@ ImGuiNavHighlightFlags_NoRounding
Definition: imgui_internal.h:622
ImGuiWindow::OuterRectClipped
ImRect OuterRectClipped
Definition: imgui_internal.h:1510
ImGuiInputTextState::CurLenA
int CurLenA
Definition: imgui_internal.h:775
ImGuiStyle::FrameBorderSize
float FrameBorderSize
Definition: imgui.h:1380
ImGuiDataTypeInfo::PrintFmt
const char * PrintFmt
Definition: imgui_internal.h:722
ImGuiWindowFlags_NoMove
@ ImGuiWindowFlags_NoMove
Definition: imgui.h:771
ImGuiInputTextFlags_AllowTabInput
@ ImGuiInputTextFlags_AllowTabInput
Definition: imgui.h:820
ImGuiTabBarFlags_NoTooltip
@ ImGuiTabBarFlags_NoTooltip
Definition: imgui.h:890
ImGuiColorEditFlags_PickerHueWheel
@ ImGuiColorEditFlags_PickerHueWheel
Definition: imgui.h:1210
ImGuiNextWindowData::Flags
ImGuiNextWindowDataFlags Flags
Definition: imgui_internal.h:957
ImGuiWindowTempData::MenuBarAppending
bool MenuBarAppending
Definition: imgui_internal.h:1395
ImGuiInputTextCallbackData::Buf
char * Buf
Definition: imgui.h:1571
ImGuiWindow::ColumnsStorage
ImVector< ImGuiColumns > ColumnsStorage
Definition: imgui_internal.h:1521
ImDrawCornerFlags_Left
@ ImDrawCornerFlags_Left
Definition: imgui.h:1940
ImGui::PushColumnClipRect
IMGUI_API void PushColumnClipRect(int column_index)
Definition: imgui_widgets.cpp:7433
ImGui::GetTextLineHeight
IMGUI_API float GetTextLineHeight()
Definition: imgui.cpp:7105
ImGui::NavMoveRequestButNoResultYet
IMGUI_API bool NavMoveRequestButNoResultYet()
Definition: imgui.cpp:8188
ImGui::EndTabItem
IMGUI_API void EndTabItem()
Definition: imgui_widgets.cpp:6973
ImGuiMenuColumns::Spacing
float Spacing
Definition: imgui_internal.h:760
ImGuiCol_Tab
@ ImGuiCol_Tab
Definition: imgui.h:1119
ImWchar
ImWchar16 ImWchar
Definition: imgui.h:185
ImDrawCornerFlags_BotRight
@ ImDrawCornerFlags_BotRight
Definition: imgui.h:1937
ImLerp
static T ImLerp(T a, T b, float t)
Definition: imgui_internal.h:323
ImGui::EndColumns
IMGUI_API void EndColumns()
Definition: imgui_widgets.cpp:7621
ImGuiWindowTempData::TreeJumpToParentOnPopMask
ImU32 TreeJumpToParentOnPopMask
Definition: imgui_internal.h:1399
ImGuiDragFlags_None
@ ImGuiDragFlags_None
Definition: imgui_internal.h:475
ImGuiInputTextCallbackData
Definition: imgui.h:1560
ImFmod
#define ImFmod(X, Y)
Definition: imgui_internal.h:307
ImGuiStorage::SetInt
IMGUI_API void SetInt(ImGuiID key, int val)
Definition: imgui.cpp:1985
ImRect::GetHeight
float GetHeight() const
Definition: imgui_internal.h:697
ImGui::IsNavInputDown
bool IsNavInputDown(ImGuiNavInput n)
Definition: imgui_internal.h:1778
ImGui::InputScalar
IMGUI_API bool InputScalar(const char *label, ImGuiDataType data_type, void *p_data, const void *p_step=NULL, const void *p_step_fast=NULL, const char *format=NULL, ImGuiInputTextFlags flags=0)
Definition: imgui_widgets.cpp:2910
size
GLsizeiptr size
Definition: glcorearb.h:2943
v0
GLfloat v0
Definition: glcorearb.h:3085
ImGui::PopTextWrapPos
IMGUI_API void PopTextWrapPos()
Definition: imgui.cpp:6229
ImGuiStyle::Colors
ImVec4 Colors[ImGuiCol_COUNT]
Definition: imgui.h:1402
ImDrawList::PathLineTo
void PathLineTo(const ImVec2 &pos)
Definition: imgui.h:2025
ImGuiInputTextCallbackData::BufSize
int BufSize
Definition: imgui.h:1573
ImGuiWindow::Size
ImVec2 Size
Definition: imgui_internal.h:1462
ImVector::resize
void resize(int new_size)
Definition: imgui.h:1337
GetMinimumStepAtDecimalPrecision
static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
Definition: imgui_widgets.cpp:1886
ImQsort
#define ImQsort
Definition: imgui_internal.h:214
ImGuiWindowFlags_NoNavFocus
@ ImGuiWindowFlags_NoNavFocus
Definition: imgui.h:787
ImGuiSelectableFlags_NoHoldingActiveID
@ ImGuiSelectableFlags_NoHoldingActiveID
Definition: imgui_internal.h:494
ImDrawCornerFlags_Right
@ ImDrawCornerFlags_Right
Definition: imgui.h:1941
ImGui::TextEx
IMGUI_API void TextEx(const char *text, const char *text_end=NULL, ImGuiTextFlags flags=0)
Definition: imgui_widgets.cpp:139
ImFont::Ascent
float Ascent
Definition: imgui.h:2293
ImGui::Begin
IMGUI_API bool Begin(const char *name, bool *p_open=NULL, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:5397
ImGuiDragFlags
int ImGuiDragFlags
Definition: imgui_internal.h:105
STB_TEXTEDIT_K_DOWN
#define STB_TEXTEDIT_K_DOWN
Definition: imgui_widgets.cpp:3270
pad
int pad
Definition: statusor_test.cc:47
ImStb::stb_textedit_replace
static void stb_textedit_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, const STB_TEXTEDIT_CHARTYPE *text, int text_len)
Definition: imgui_widgets.cpp:3288
ImSubClampOverflow
static T ImSubClampOverflow(T a, T b, T mn, T mx)
Definition: imgui_internal.h:326
ImGui::ItemSize
IMGUI_API void ItemSize(const ImVec2 &size, float text_baseline_y=-1.0f)
Definition: imgui.cpp:6823
ImGui::PushMultiItemsWidths
IMGUI_API void PushMultiItemsWidths(int components, float width_full)
Definition: imgui.cpp:7039
ImGui::BeginTooltipEx
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags)
Definition: imgui.cpp:7440
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:2672
ImVec4::w
float w
Definition: imgui.h:223
ImGuiColumns
Definition: imgui_internal.h:855
ImGui::IsMouseDragging
IMGUI_API bool IsMouseDragging(ImGuiMouseButton button, float lock_threshold=-1.0f)
Definition: imgui.cpp:4475
ImGuiTabBarFlags_NoTabListScrollingButtons
@ ImGuiTabBarFlags_NoTabListScrollingButtons
Definition: imgui.h:889
ImGuiWindow::MenuBarHeight
float MenuBarHeight() const
Definition: imgui_internal.h:1557
STB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_CHARTYPE
Definition: imgui_internal.h:128
ImGui::GetInputTextState
ImGuiInputTextState * GetInputTextState(ImGuiID id)
Definition: imgui_internal.h:1877
ImGuiColorEditFlags_DisplayHex
@ ImGuiColorEditFlags_DisplayHex
Definition: imgui.h:1206
ImGuiStyle::WindowPadding
ImVec2 WindowPadding
Definition: imgui.h:1368
ImGuiTreeNodeFlags_DefaultOpen
@ ImGuiTreeNodeFlags_DefaultOpen
Definition: imgui.h:843
ImGuiDragDropFlags_SourceNoHoldToOpenOthers
@ ImGuiDragDropFlags_SourceNoHoldToOpenOthers
Definition: imgui.h:942
ImGuiMouseCursor_TextInput
@ ImGuiMouseCursor_TextInput
Definition: imgui.h:1246
ImDrawListSplitter::Split
IMGUI_API void Split(ImDrawList *draw_list, int count)
Definition: imgui_draw.cpp:1318
ImGuiSliderFlags_Vertical
@ ImGuiSliderFlags_Vertical
Definition: imgui_internal.h:470
ImGuiTabBar::GetTabName
const char * GetTabName(const ImGuiTabItem *tab) const
Definition: imgui_internal.h:1637
ImGuiContext::TempBuffer
char TempBuffer[1024 *3+1]
Definition: imgui_internal.h:1226
ImGui::DataTypeFormatString
IMGUI_API int DataTypeFormatString(char *buf, int buf_size, ImGuiDataType data_type, const void *p_data, const char *format)
Definition: imgui_widgets.cpp:1710
ImGui::ButtonBehavior
IMGUI_API bool ButtonBehavior(const ImRect &bb, ImGuiID id, bool *out_hovered, bool *out_held, ImGuiButtonFlags flags=0)
Definition: imgui_widgets.cpp:459
ImGui::PushStyleVar
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val)
Definition: imgui.cpp:2452
r
GLboolean r
Definition: glcorearb.h:3228
ImGuiTabBar::OffsetNextTab
float OffsetNextTab
Definition: imgui_internal.h:1621
ImSin
#define ImSin(X)
Definition: imgui_internal.h:309
ImVector::empty
bool empty() const
Definition: imgui.h:1318
ImGuiStorage
Definition: imgui.h:1729
ImGuiCol_SliderGrabActive
@ ImGuiCol_SliderGrabActive
Definition: imgui.h:1106
ImGuiColorEditFlags_NoOptions
@ ImGuiColorEditFlags_NoOptions
Definition: imgui.h:1190
dst
GLenum GLenum dst
Definition: glcorearb.h:3364
ImGuiStyle::TouchExtraPadding
ImVec2 TouchExtraPadding
Definition: imgui.h:1383
ImGuiItemFlags_ButtonRepeat
@ ImGuiItemFlags_ButtonRepeat
Definition: imgui_internal.h:522
ImGui::ColorPicker3
IMGUI_API bool ColorPicker3(const char *label, float col[3], ImGuiColorEditFlags flags=0)
Definition: imgui_widgets.cpp:4487
ImGuiWindow::IDStack
ImVector< ImGuiID > IDStack
Definition: imgui_internal.h:1505
ImGuiInputTextState::SelectedAllMouseLock
bool SelectedAllMouseLock
Definition: imgui_internal.h:785
ImGui::TreePush
IMGUI_API void TreePush(const char *str_id)
Definition: imgui_widgets.cpp:5455
ImGuiTreeNodeFlags_Bullet
@ ImGuiTreeNodeFlags_Bullet
Definition: imgui.h:847
ImGui::BeginMenuBar
IMGUI_API bool BeginMenuBar()
Definition: imgui_widgets.cpp:6082
ImGui::TabItemBackground
IMGUI_API void TabItemBackground(ImDrawList *draw_list, const ImRect &bb, ImGuiTabItemFlags flags, ImU32 col)
Definition: imgui_widgets.cpp:7217
ImGuiWindow::Rect
ImRect Rect() const
Definition: imgui_internal.h:1553
COLUMNS_HIT_RECT_HALF_WIDTH
static const float COLUMNS_HIT_RECT_HALF_WIDTH
Definition: imgui_widgets.cpp:7339
ImGuiTabItemFlags_UnsavedDocument
@ ImGuiTabItemFlags_UnsavedDocument
Definition: imgui.h:901
ImGuiItemStatusFlags_HasDisplayRect
@ ImGuiItemStatusFlags_HasDisplayRect
Definition: imgui_internal.h:536
ImGui::MemFree
IMGUI_API void MemFree(void *ptr)
Definition: imgui.cpp:3218
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:2200
TYPE
#define TYPE(u, l)
Definition: php/ext/google/protobuf/upb.c:8510
ImGuiButtonFlags_MouseButtonMask_
@ ImGuiButtonFlags_MouseButtonMask_
Definition: imgui_internal.h:460
ImParseFormatTrimDecorations
const char * ImParseFormatTrimDecorations(const char *fmt, char *buf, size_t buf_size)
Definition: imgui_widgets.cpp:2828
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:2205
ImGuiCol_FrameBg
@ ImGuiCol_FrameBg
Definition: imgui.h:1093
ImGuiColumnData::Flags
ImGuiColumnsFlags Flags
Definition: imgui_internal.h:849
ImGui::TabBarQueueChangeTabOrder
IMGUI_API void TabBarQueueChangeTabOrder(ImGuiTabBar *tab_bar, const ImGuiTabItem *tab, int dir)
Definition: imgui_widgets.cpp:6842
ImGuiTabBarFlags_FittingPolicyDefault_
@ ImGuiTabBarFlags_FittingPolicyDefault_
Definition: imgui.h:894
ImGuiIO
Definition: imgui.h:1414
IM_ASSERT_USER_ERROR
#define IM_ASSERT_USER_ERROR(_EXP, _MSG)
Definition: imgui_internal.h:172
ImFont
Definition: imgui.h:2272
PatchFormatStringFloatToInt
static const char * PatchFormatStringFloatToInt(const char *fmt)
Definition: imgui_widgets.cpp:1683
ImGuiColumnData
Definition: imgui_internal.h:845
ImGui::DataTypeApplyOp
IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void *output, void *arg_1, const void *arg_2)
Definition: imgui_widgets.cpp:1733
ImGuiButtonFlags_FlattenChildren
@ ImGuiButtonFlags_FlattenChildren
Definition: imgui_internal.h:447
STB_TEXTEDIT_K_SHIFT
#define STB_TEXTEDIT_K_SHIFT
Definition: imgui_widgets.cpp:3281
ImGuiMenuColumns::Update
void Update(int count, float spacing, bool clear)
Definition: imgui_widgets.cpp:6044
ImGuiInputTextFlags
int ImGuiInputTextFlags
Definition: imgui.h:162
ImGuiWindowTempData::Indent
ImVec1 Indent
Definition: imgui_internal.h:1375
ImGuiStyle::FramePadding
ImVec2 FramePadding
Definition: imgui.h:1378
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: glcorearb.h:2879
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:5788
ImCharIsBlankA
static bool ImCharIsBlankA(char c)
Definition: imgui_internal.h:247
ImGui::FocusWindow
IMGUI_API void FocusWindow(ImGuiWindow *window)
Definition: imgui.cpp:6085
ImGuiMenuColumns::Pos
float Pos[3]
Definition: imgui_internal.h:762
Items_SingleStringGetter
static bool Items_SingleStringGetter(void *data, int idx, const char **out_text)
Definition: imgui_widgets.cpp:1566
ImGuiTabBar::CurrFrameVisible
int CurrFrameVisible
Definition: imgui_internal.h:1615
ImGuiColumns::IsFirstFrame
bool IsFirstFrame
Definition: imgui_internal.h:859
ImGuiButtonFlags_PressedOnDefault_
@ ImGuiButtonFlags_PressedOnDefault_
Definition: imgui_internal.h:464
ImGuiKey_Backspace
@ ImGuiKey_Backspace
Definition: imgui.h:998
ImGuiComboFlags_NoArrowButton
@ ImGuiComboFlags_NoArrowButton
Definition: imgui.h:876
ImVec4
Definition: imgui.h:221
ImGuiItemStatusFlags_ToggledOpen
@ ImGuiItemStatusFlags_ToggledOpen
Definition: imgui_internal.h:539
ImGuiColumns::LineMinY
float LineMinY
Definition: imgui_internal.h:864
ImGuiStyleVar_WindowPadding
@ ImGuiStyleVar_WindowPadding
Definition: imgui.h:1154
ImStb::STB_TEXTEDIT_MOVEWORDLEFT_IMPL
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui_widgets.cpp:3210
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:2903
ImGui::RenderTextWrapped
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char *text, const char *text_end, float wrap_width)
Definition: imgui.cpp:2600
ImVector::contains
bool contains(const T &v) const
Definition: imgui.h:1350
ImStrTrimBlanks
void ImStrTrimBlanks(char *buf)
Definition: imgui.cpp:1397
ImGui::NextColumn
IMGUI_API void NextColumn()
Definition: imgui_widgets.cpp:7570
IM_ASSERT
#define IM_ASSERT(_EXPR)
Definition: imgui.h:79
ImStb::is_word_boundary_from_right
static int is_word_boundary_from_right(STB_TEXTEDIT_STRING *obj, int idx)
Definition: imgui_widgets.cpp:3209
ImGuiColumnsFlags_NoPreserveWidths
@ ImGuiColumnsFlags_NoPreserveWidths
Definition: imgui_internal.h:485
ImGuiKey_UpArrow
@ ImGuiKey_UpArrow
Definition: imgui.h:990
ImGui::SetClipboardText
IMGUI_API void SetClipboardText(const char *text)
Definition: imgui.cpp:3232
ImGui::GetFrameHeight
IMGUI_API float GetFrameHeight()
Definition: imgui.cpp:7117
ImGui::CloseCurrentPopup
IMGUI_API void CloseCurrentPopup()
Definition: imgui.cpp:7634
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:972
IM_F32_TO_INT8_SAT
#define IM_F32_TO_INT8_SAT(_VAL)
Definition: imgui_internal.h:184
ImFontGlyph::AdvanceX
float AdvanceX
Definition: imgui.h:2124
IM_PI
#define IM_PI
Definition: imgui_internal.h:176
ImDrawList::AddImage
IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2 &p_min, const ImVec2 &p_max, const ImVec2 &uv_min=ImVec2(0, 0), const ImVec2 &uv_max=ImVec2(1, 1), ImU32 col=IM_COL32_WHITE)
Definition: imgui_draw.cpp:1240
ImGui::IsRectVisible
IMGUI_API bool IsRectVisible(const ImVec2 &size)
Definition: imgui.cpp:6674
ImGuiPlotType
ImGuiPlotType
Definition: imgui_internal.h:589
ImGuiWindowFlags_NoTitleBar
@ ImGuiWindowFlags_NoTitleBar
Definition: imgui.h:769
ImGuiTabItem::LastFrameVisible
int LastFrameVisible
Definition: imgui_internal.h:1597
STB_TEXTEDIT_K_BACKSPACE
#define STB_TEXTEDIT_K_BACKSPACE
Definition: imgui_widgets.cpp:3276
f
GLfloat f
Definition: glcorearb.h:3964
ImGuiCol_BorderShadow
@ ImGuiCol_BorderShadow
Definition: imgui.h:1092
ImGuiTextFlags
int ImGuiTextFlags
Definition: imgui_internal.h:115
ImGui::BeginTabBarEx
IMGUI_API bool BeginTabBarEx(ImGuiTabBar *tab_bar, const ImRect &bb, ImGuiTabBarFlags flags)
Definition: imgui_widgets.cpp:6505
ImGuiColorEditFlags__DisplayMask
@ ImGuiColorEditFlags__DisplayMask
Definition: imgui.h:1219
ImGuiInputTextState::UserFlags
ImGuiInputTextFlags UserFlags
Definition: imgui_internal.h:786
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:2667
IM_UNICODE_CODEPOINT_MAX
#define IM_UNICODE_CODEPOINT_MAX
Definition: imgui.h:1662
ImGui::GetStyle
IMGUI_API ImGuiStyle & GetStyle()
Definition: imgui.cpp:2339
ImGuiInputTextFlags_CtrlEnterForNewLine
@ ImGuiInputTextFlags_CtrlEnterForNewLine
Definition: imgui.h:821
ImGui::BeginMainMenuBar
IMGUI_API bool BeginMainMenuBar()
Definition: imgui_widgets.cpp:6152
ImGuiComboFlags
int ImGuiComboFlags
Definition: imgui.h:158
ImGuiInputTextCallbackData::ImGuiInputTextCallbackData
IMGUI_API ImGuiInputTextCallbackData()
Definition: imgui_widgets.cpp:3312
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:922
ImGuiKey_Insert
@ ImGuiKey_Insert
Definition: imgui.h:996
ImGuiWindowTempData::LastItemId
ImGuiID LastItemId
Definition: imgui_internal.h:1380
ImGuiNextItemDataFlags_HasOpen
@ ImGuiNextItemDataFlags_HasOpen
Definition: imgui_internal.h:980
ImGuiTabItemFlags_SetSelected
@ ImGuiTabItemFlags_SetSelected
Definition: imgui.h:902
ImGuiInputTextFlags_CharsUppercase
@ ImGuiInputTextFlags_CharsUppercase
Definition: imgui.h:812
ImGuiInputTextFlags_AlwaysInsertMode
@ ImGuiInputTextFlags_AlwaysInsertMode
Definition: imgui.h:823
ImGuiTabItem::Flags
ImGuiTabItemFlags Flags
Definition: imgui_internal.h:1596
ImGuiMenuColumns::ImGuiMenuColumns
ImGuiMenuColumns()
Definition: imgui_widgets.cpp:6037
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:4128
STB_TexteditState::cursor
int cursor
Definition: imstb_textedit.h:326
google::protobuf::python::descriptor::Index
static PyObject * Index(PyContainer *self, PyObject *item)
Definition: descriptor_containers.cc:671
ImGuiLayoutType_Horizontal
@ ImGuiLayoutType_Horizontal
Definition: imgui_internal.h:568
ImGui::ArrowButtonEx
IMGUI_API bool ArrowButtonEx(const char *str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags=0)
Definition: imgui_widgets.cpp:718
ImGuiButtonFlags_None
@ ImGuiButtonFlags_None
Definition: imgui_internal.h:439
ImGuiWindowFlags_NoResize
@ ImGuiWindowFlags_NoResize
Definition: imgui.h:770
ImRect::ClipWith
void ClipWith(const ImRect &r)
Definition: imgui_internal.h:712
ImGuiDataType_S16
@ ImGuiDataType_S16
Definition: imgui.h:962
ImGui::SetTabItemClosed
IMGUI_API void SetTabItemClosed(const char *tab_or_docked_window_label)
Definition: imgui_widgets.cpp:7192
ImGuiContext::CurrentWindow
ImGuiWindow * CurrentWindow
Definition: imgui_internal.h:1043
ImGui::EndChild
IMGUI_API void EndChild()
Definition: imgui.cpp:4755
IM_S64_MIN
static const ImS64 IM_S64_MIN
Definition: imgui_widgets.cpp:101
ImGui::TempInputText
IMGUI_API bool TempInputText(const ImRect &bb, ImGuiID id, const char *label, char *buf, int buf_size, ImGuiInputTextFlags flags)
Definition: imgui_widgets.cpp:2866
ImGuiWindowTempData::ParentLayoutType
ImGuiLayoutType ParentLayoutType
Definition: imgui_internal.h:1404
ImGuiWindow::GetID
ImGuiID GetID(const char *str, const char *str_end=NULL)
Definition: imgui.cpp:2879
output
const upb_json_parsermethod const upb_symtab upb_sink * output
Definition: ruby/ext/google/protobuf_c/upb.h:10503
ImGuiColorEditFlags_Float
@ ImGuiColorEditFlags_Float
Definition: imgui.h:1208
w
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:3126
STB_TEXTEDIT_K_WORDLEFT
#define STB_TEXTEDIT_K_WORDLEFT
Definition: imgui_widgets.cpp:3279
ImGuiColorEditFlags_NoSmallPreview
@ ImGuiColorEditFlags_NoSmallPreview
Definition: imgui.h:1191
ImVector::pop_back
void pop_back()
Definition: imgui.h:1344
StbTexteditRow
Definition: imstb_textedit.h:362
ImGuiDir_Right
@ ImGuiDir_Right
Definition: imgui.h:978
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:5193
ImGuiWindowTempData::CurrLineTextBaseOffset
float CurrLineTextBaseOffset
Definition: imgui_internal.h:1373
ImGuiTabBar::BarRect
ImRect BarRect
Definition: imgui_internal.h:1617
ImGuiGroupData::EmitItem
bool EmitItem
Definition: imgui_internal.h:754
ImGui::TabBarScrollClamp
static float TabBarScrollClamp(ImGuiTabBar *tab_bar, float scrolling)
Definition: imgui_widgets.cpp:6816
ImCos
#define ImCos(X)
Definition: imgui_internal.h:308
ImGui::OpenPopup
IMGUI_API void OpenPopup(const char *str_id)
Definition: imgui.cpp:7519
count
GLint GLsizei count
Definition: glcorearb.h:2830
ImGuiCol_ScrollbarBg
@ ImGuiCol_ScrollbarBg
Definition: imgui.h:1100
ImGuiIO::DeltaTime
float DeltaTime
Definition: imgui.h:1423
ImGuiTabBar::ScrollingTargetDistToVisibility
float ScrollingTargetDistToVisibility
Definition: imgui_internal.h:1624
ImGuiDataType_S8
@ ImGuiDataType_S8
Definition: imgui.h:960
ImGuiCol_FrameBgHovered
@ ImGuiCol_FrameBgHovered
Definition: imgui.h:1094
STB_TEXTEDIT_K_RIGHT
#define STB_TEXTEDIT_K_RIGHT
Definition: imgui_widgets.cpp:3268
ref
GLint ref
Definition: glcorearb.h:2789
ImGui::PushColumnsBackground
IMGUI_API void PushColumnsBackground()
Definition: imgui_widgets.cpp:7445
ImGui::OpenPopupEx
IMGUI_API void OpenPopupEx(ImGuiID id)
Definition: imgui.cpp:7529
ImGuiWindow::ContentRegionRect
ImRect ContentRegionRect
Definition: imgui_internal.h:1515
ImGuiInputTextFlags_NoMarkEdited
@ ImGuiInputTextFlags_NoMarkEdited
Definition: imgui.h:831
ImGui::EndDragDropTarget
IMGUI_API void EndDragDropTarget()
Definition: imgui.cpp:9294
ImDrawList::AddCircle
IMGUI_API void AddCircle(const ImVec2 &center, float radius, ImU32 col, int num_segments=12, float thickness=1.0f)
Definition: imgui_draw.cpp:1111
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:2682
ImGuiDragFlags_Vertical
@ ImGuiDragFlags_Vertical
Definition: imgui_internal.h:476
ImLengthSqr
static float ImLengthSqr(const ImVec2 &lhs)
Definition: imgui_internal.h:335
ImGuiTabBar::VisibleTabId
ImGuiID VisibleTabId
Definition: imgui_internal.h:1614
STB_TEXTEDIT_K_TEXTEND
#define STB_TEXTEDIT_K_TEXTEND
Definition: imgui_widgets.cpp:3274
ImGui::TabItemEx
IMGUI_API bool TabItemEx(ImGuiTabBar *tab_bar, const char *label, bool *p_open, ImGuiTabItemFlags flags)
Definition: imgui_widgets.cpp:6992
ImGuiTabItemFlags
int ImGuiTabItemFlags
Definition: imgui.h:166
ImGuiTabItem
Definition: imgui_internal.h:1593
ImGuiCol_SeparatorHovered
@ ImGuiCol_SeparatorHovered
Definition: imgui.h:1114
ImGuiTreeNodeFlags_NavLeftJumpsBackHere
@ ImGuiTreeNodeFlags_NavLeftJumpsBackHere
Definition: imgui.h:851
ImGui::RenderTextEllipsis
IMGUI_API void RenderTextEllipsis(ImDrawList *draw_list, const ImVec2 &pos_min, const ImVec2 &pos_max, float clip_max_x, float ellipsis_max_x, const char *text, const char *text_end, const ImVec2 *text_size_if_known)
Definition: imgui.cpp:2665
ImGuiButtonFlags_PressedOnMask_
@ ImGuiButtonFlags_PressedOnMask_
Definition: imgui_internal.h:463
ImGuiWindowTempData::CurrLineSize
ImVec2 CurrLineSize
Definition: imgui_internal.h:1371
ImGui::CloseButton
IMGUI_API bool CloseButton(ImGuiID id, const ImVec2 &pos)
Definition: imgui_widgets.cpp:755
IM_COL32
#define IM_COL32(R, G, B, A)
Definition: imgui.h:1820
ImGui::SetColumnOffset
IMGUI_API void SetColumnOffset(int column_index, float offset_x)
Definition: imgui_widgets.cpp:7400
ImVector::back
T & back()
Definition: imgui.h:1332
ImGui::TabBarTabListPopupButton
static ImGuiTabItem * TabBarTabListPopupButton(ImGuiTabBar *tab_bar)
Definition: imgui_widgets.cpp:6904
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:3228
ImGuiMouseCursor_ResizeNS
@ ImGuiMouseCursor_ResizeNS
Definition: imgui.h:1248
ImGui::GetColumnsID
IMGUI_API ImGuiID GetColumnsID(const char *str_id, int count)
Definition: imgui_widgets.cpp:7481
ImGui::GetCurrentWindowRead
ImGuiWindow * GetCurrentWindowRead()
Definition: imgui_internal.h:1656
ImFont::FallbackGlyph
const ImFontGlyph * FallbackGlyph
Definition: imgui.h:2282
ImGui::GetScrollMaxY
IMGUI_API float GetScrollMaxY()
Definition: imgui.cpp:7347
ImGui::EndChildFrame
IMGUI_API void EndChildFrame()
Definition: imgui.cpp:4813
ImRect::GetTR
ImVec2 GetTR() const
Definition: imgui_internal.h:699
ImGuiColorEditFlags_InputRGB
@ ImGuiColorEditFlags_InputRGB
Definition: imgui.h:1211
ImGui::GetColorU32
IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul=1.0f)
Definition: imgui.cpp:2345
ImTextCharFromUtf8
int ImTextCharFromUtf8(unsigned int *out_char, const char *in_text, const char *in_text_end)
Definition: imgui.cpp:1621
ImFont::Glyphs
ImVector< ImFontGlyph > Glyphs
Definition: imgui.h:2281
ImGuiTabBar::ScrollingAnim
float ScrollingAnim
Definition: imgui_internal.h:1622
ImGui::EndMenu
IMGUI_API void EndMenu()
Definition: imgui_widgets.cpp:6349
ImGuiButtonFlags_DontClosePopups
@ ImGuiButtonFlags_DontClosePopups
Definition: imgui_internal.h:449
ImFont::FallbackAdvanceX
float FallbackAdvanceX
Definition: imgui.h:2276
ImDrawList::PathFillConvex
void PathFillConvex(ImU32 col)
Definition: imgui.h:2027
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:5965
ImGuiInputTextCallbackData::SelectionEnd
int SelectionEnd
Definition: imgui.h:1577
ImParseFormatFindEnd
const char * ImParseFormatFindEnd(const char *fmt)
Definition: imgui_widgets.cpp:2806
ImGui::PopFont
IMGUI_API void PopFont()
Definition: imgui.cpp:6176
ImGuiDataType_U8
@ ImGuiDataType_U8
Definition: imgui.h:961
ImGui::EndPopup
IMGUI_API void EndPopup()
Definition: imgui.cpp:7729
ImGuiKey_Tab
@ ImGuiKey_Tab
Definition: imgui.h:987
ImGui::KeepAliveID
IMGUI_API void KeepAliveID(ImGuiID id)
Definition: imgui.cpp:3021
ImDrawList::PathArcToFast
IMGUI_API void PathArcToFast(const ImVec2 &center, float radius, int a_min_of_12, int a_max_of_12)
Definition: imgui_draw.cpp:894
ImGui::BulletText
IMGUI_API void BulletText(const char *fmt,...) IM_FMTARGS(1)
Definition: imgui_widgets.cpp:349
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:3017
ImDrawList::AddRect
IMGUI_API void AddRect(const ImVec2 &p_min, const ImVec2 &p_max, ImU32 col, float rounding=0.0f, ImDrawCornerFlags rounding_corners=ImDrawCornerFlags_All, float thickness=1.0f)
Definition: imgui_draw.cpp:1022
ImGuiTabItem::ID
ImGuiID ID
Definition: imgui_internal.h:1595
ImGui::PushOverrideID
IMGUI_API void PushOverrideID(ImGuiID id)
Definition: imgui.cpp:6644
ImGuiCol_CheckMark
@ ImGuiCol_CheckMark
Definition: imgui.h:1104
ImDrawList::PathStroke
void PathStroke(ImU32 col, bool closed, float thickness=1.0f)
Definition: imgui.h:2028
ImGuiButtonFlags_PressedOnDoubleClick
@ ImGuiButtonFlags_PressedOnDoubleClick
Definition: imgui_internal.h:445
ImVec2::y
float y
Definition: imgui.h:210
ImGui::TabBarRemoveTab
IMGUI_API void TabBarRemoveTab(ImGuiTabBar *tab_bar, ImGuiID tab_id)
Definition: imgui_widgets.cpp:6790
width
GLint GLsizei width
Definition: glcorearb.h:2768
benchmarks.python.py_benchmark.args
args
Definition: py_benchmark.py:24
ImGuiItemFlags_SelectableDontClosePopup
@ ImGuiItemFlags_SelectableDontClosePopup
Definition: imgui_internal.h:526
ImGuiIO::SetClipboardTextFn
void(* SetClipboardTextFn)(void *user_data, const char *text)
Definition: imgui.h:1464
ImGuiStyle::ButtonTextAlign
ImVec2 ButtonTextAlign
Definition: imgui.h:1393
ImFont::DisplayOffset
ImVec2 DisplayOffset
Definition: imgui.h:2283
ImGui::SetNavID
IMGUI_API void SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id)
Definition: imgui.cpp:7909
ImGuiTreeNodeFlags_CollapsingHeader
@ ImGuiTreeNodeFlags_CollapsingHeader
Definition: imgui.h:853
ImU16
unsigned short ImU16
Definition: imgui.h:192
ImGuiTreeNodeFlags_OpenOnArrow
@ ImGuiTreeNodeFlags_OpenOnArrow
Definition: imgui.h:845
ImGuiSeparatorFlags_Vertical
@ ImGuiSeparatorFlags_Vertical
Definition: imgui_internal.h:512
ImGui::NewLine
IMGUI_API void NewLine()
Definition: imgui_widgets.cpp:1226
ImGui::TabBarLayout
static void TabBarLayout(ImGuiTabBar *tab_bar)
Definition: imgui_widgets.cpp:6589
ImGuiComboFlags_HeightLarge
@ ImGuiComboFlags_HeightLarge
Definition: imgui.h:874
ImGuiMenuColumns::NextWidth
float NextWidth
Definition: imgui_internal.h:761
ImGuiTabItem::ContentWidth
float ContentWidth
Definition: imgui_internal.h:1602
ImGui::BeginChildFrame
IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2 &size, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:4799
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:944
ImGuiWindowTempData::LastItemRect
ImRect LastItemRect
Definition: imgui_internal.h:1382
ImGuiKey_V
@ ImGuiKey_V
Definition: imgui.h:1005


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:54