35 private static char[] formatBuffer =
new char[256];
37 private static bool checkboxValue;
38 private static int selectedValue = -1;
39 private static float bouncingBallSize = 22;
40 private static float bouncingBallSpeed = 1;
41 private static int bouncingBallTrail = 32;
42 private static float bouncingBallTime;
44 private static string[] values =
46 "Value 1",
"Value 2",
"Value 3",
"Value 4",
"Value 5",
"Value 6",
"Value 7",
"Value 8",
"Value 9",
"Value 10",
"Value 11",
"Value 12"
49 private static string textWithHint =
string.Empty;
50 private static string singleLineText =
"Single line text edit";
51 private static string multiLineText =
"Multiline text\nedit";
52 private static float floatValue = 10.5f;
53 private static int intValue = 105;
54 private static bool isReadOnly;
55 private static bool customDropdownOpen;
56 private static ImDropdownPreviewType dropdownPreview;
57 private static bool[] checkboxes =
new bool[4];
58 private static int clicks;
59 private static int nestedFoldouts;
60 private static bool showPlusMinusButtons =
true;
61 private static bool useNumericSlider =
false;
62 private static DemoEnumFlags demoFlags;
63 private static int largeTableRows = 1024 * 128;
64 private static int largeTableColumns = 512;
65 private static float largeTableColumnSize = 150;
66 private static bool largeTableScrollable =
true;
67 private static bool largeTableResizable =
true;
68 private static Vector2 vec2 =
new Vector2(1.0f, 2.0f);
69 private static Vector3 vec3 =
new Vector3(1.0f, 2.0f, 3.0f);
70 private static Vector4 vec4 =
new Vector4(1.0f, 2.0f, 3.0f, 4.0f);
71 private static Vector2Int vec2int =
new Vector2Int(1, 2);
72 private static Vector3Int vec3int =
new Vector3Int(1, 2, 3);
73 private static bool textEditWrap;
75 private static bool selectMultipleValues =
false;
76 private static HashSet<string> selectedNodes =
new HashSet<string>(8);
78 private static readonly DemoTreeNode[] treeNodes =
new[]
80 new DemoTreeNode(
"Node 0",
81 new DemoTreeNode(
"Node 1"),
82 new DemoTreeNode(
"Node 2")),
83 new DemoTreeNode(
"Node 3"),
new DemoTreeNode(
"Node 4",
84 new DemoTreeNode(
"Node 5",
85 new DemoTreeNode(
"Node 6"),
86 new DemoTreeNode(
"Node 7")))
89 private static HashSet<int> selectedValues =
new HashSet<int>(values.Length);
91 public static void Draw(ImGui gui, ref
bool open)
93 if (!gui.BeginWindow(
"Demo", ref open, (700, 700), ImWindowFlag.HasMenuBar))
99 DrawMenuBarItems(gui, ref open);
102 if (gui.BeginFoldout(
"Controls"))
105 DrawControlsPage(gui, ref open);
111 gui.BeginReadOnly(isReadOnly);
113 if (gui.BeginFoldout(
"Layout"))
122 if (gui.BeginFoldout(
"Tables"))
135 private static void DrawControlsPage(ImGui gui, ref
bool open)
137 gui.Checkbox(ref isReadOnly,
"Read Only");
139 gui.BeginReadOnly(isReadOnly);
141 gui.AddSpacingIfLayoutFrameNotEmpty();
142 gui.BeginHorizontal();
143 if (gui.Button(Format(
"Clicks ", clicks,
"0"), ImSizeMode.Fit))
148 if (gui.Button(
"Reset Clicks", ImSizeMode.Auto))
155 gui.Checkbox(ref checkboxValue,
"Checkbox");
156 gui.AddSpacingIfLayoutFrameNotEmpty();
157 gui.BeginHorizontal();
158 gui.Text(
"Dropdown preview mode: ");
159 gui.Radio(ref dropdownPreview);
161 gui.Dropdown(ref selectedValue, values, defaultLabel:
"Dropdown without value selected", preview: dropdownPreview);
162 if (gui.BeginDropdown(
"Custom Dropdown", preview: dropdownPreview))
164 if (gui.Menu(
"Menu Item"))
168 gui.TooltipAtLastControl(
"Will close dropdown on click");
170 if (gui.BeginMenu(
"Sub Menu Inside Dropdown"))
172 gui.Text(
"Hello there");
175 gui.Checkbox(ref checkboxValue,
"Checkbox");
176 gui.Separator(
"Nested dropdown, if that's want you really want");
177 gui.Dropdown(ref selectedValue, values, defaultLabel:
"Nothing", preview: dropdownPreview);
180 gui.Separator(
"Text editors");
181 gui.TextEdit(ref textWithHint, hint:
"Write something here");
182 gui.TextEdit(ref singleLineText, multiline:
false);
183 gui.Checkbox(ref textEditWrap,
"Wrap Text");
184 using (gui.StyleScope(ref gui.Style.TextEdit.TextWrap, textEditWrap))
186 gui.TextEdit(ref multiLineText, multiline:
true);
188 gui.Separator(
"Sliders (with tooltips)");
189 DrawSlidersDemo(gui);
190 gui.Separator(
"Selection list (you can select multiple values)");
191 gui.BeginList((gui.GetLayoutWidth(), ImList.GetEnclosingHeight(gui, gui.GetRowsHeightWithSpacing(3))));
192 for (
int i = 0; i < values.Length; ++i)
194 var wasSelected = selectedValues.Contains(i);
195 if (gui.ListItem(wasSelected, values[i]))
199 selectedValues.Remove(i);
203 selectedValues.Add(i);
210 gui.Separator(
"Numeric editors");
211 gui.BeginReadOnly(useNumericSlider);
212 gui.Checkbox(ref showPlusMinusButtons,
"Enable Plus/Minus buttons");
214 gui.Checkbox(ref useNumericSlider,
"Enable Slider");
216 var numericFlag = ImNumericEditFlag.None;
217 numericFlag |= showPlusMinusButtons ? ImNumericEditFlag.PlusMinus : ImNumericEditFlag.None;
218 numericFlag |= useNumericSlider ? ImNumericEditFlag.Slider : ImNumericEditFlag.None;
221 gui.NumericEdit(ref floatValue, step: 0.05f, flags: numericFlag, format:
"0.0### kg");
222 gui.NumericEdit(ref intValue, flags: numericFlag, format:
"0 miles");
224 gui.AddSpacingIfLayoutFrameNotEmpty();
225 gui.Separator(
"Radio buttons (enum flags)");
226 gui.Radio(ref demoFlags);
228 gui.Separator(
"Dropdown (enum flags)");
229 gui.Dropdown(ref demoFlags);
231 gui.Separator(
"Trees");
234 gui.Separator(
"Nested Foldout");
237 gui.Separator(
"Floating menu");
238 var rect = gui.AddLayoutRect(gui.GetLayoutWidth(), gui.GetRowHeight());
239 gui.BeginMenuBar(rect);
240 DrawMenuBarItems(gui, ref open);
243 gui.Separator(
"Tabs");
245 gui.BeginTabsPane(gui.AddLayoutRect(gui.GetLayoutWidth(), gui.GetRowsHeightWithSpacing(2)));
246 for (
int i = 0; i < 4; ++i)
248 var label = gui.Formatter.Concat(
"Tab ", i);
249 if (gui.BeginTab(label))
257 gui.Separator(
"Vectors (float)");
258 gui.Text(
"Two component vector");
259 gui.Vector(ref vec2);
260 gui.Text(
"Three component vector");
261 gui.Vector(ref vec3);
262 gui.Text(
"Four component vector");
263 gui.Vector(ref vec4);
264 gui.Separator(
"Vectors (int)");
265 gui.Text(
"Two component vector");
266 gui.Vector(ref vec2int);
267 gui.Text(
"Three component vector");
268 gui.Vector(ref vec3int);
273 private static void DrawSelectableTreeDemo(ImGui gui)
275 gui.Checkbox(ref selectMultipleValues,
"Select multiple values");
277 gui.BeginHorizontal();
278 gui.Text(
"Selected nodes: ");
279 foreach (var name
in selectedNodes)
286 void SetSelected(
string name,
bool selected)
290 if (!selectMultipleValues)
292 selectedNodes.Clear();
295 selectedNodes.Add(name);
299 selectedNodes.Remove(name);
303 void Node(ref DemoTreeNode node)
305 var flags = (selectMultipleValues ? ImTreeNodeFlags.UnselectOnClick : ImTreeNodeFlags.None) |
306 (node.Childrens.Length == 0 ? ImTreeNodeFlags.NonExpandable : 0);
307 var isSelected = selectedNodes.Contains(node.Name);
308 var expanded = gui.BeginTreeNode(ref isSelected, node.Name, flags: flags);
310 SetSelected(node.Name, isSelected);
314 for (
int i = 0; i < node.Childrens.Length; ++i)
316 Node(ref node.Childrens[i]);
323 for (
int i = 0; i < treeNodes.Length; ++i)
325 Node(ref treeNodes[i]);
329 private static void DrawTreeDemo(ImGui gui)
331 gui.TreeNode(
"Node 0");
332 if (gui.BeginTreeNode(
"Node 1"))
334 gui.TreeNode(
"Node 3");
335 if (gui.BeginTreeNode(
"Node 4"))
337 gui.TreeNode(
"Node 5");
342 gui.TreeNode(
"Node 5");
343 if (gui.BeginTreeNode(
"Selectable nodes demo"))
345 DrawSelectableTreeDemo(gui);
350 private static void DrawSlidersDemo(ImGui gui)
353 gui.SliderHeader(
"Size", bouncingBallSize,
"0.00 px");
354 gui.Slider(ref bouncingBallSize, 1f, gui.GetRowHeight());
355 gui.TooltipAtLastControl(
"Size of the circles in pixels");
356 gui.SliderHeader(
"Speed", bouncingBallSpeed,
"0.##");
357 gui.Slider(ref bouncingBallSpeed, -2f, 2f);
358 gui.TooltipAtLastControl(
"Speed of moving circles");
359 gui.SliderHeader(
"Trail Length", bouncingBallTrail);
360 gui.Slider(ref bouncingBallTrail, 1, 256, step: 32, flags: ImSliderFlag.DynamicHandle);
361 gui.TooltipAtLastControl(
"Number of circles drawn");
364 private static void DrawMenuBarItems(ImGui gui, ref
bool windowOpen)
366 if (gui.BeginMenu(
"Demo"))
368 if (gui.BeginMenu(
"Custom Menus"))
370 gui.BeginVertical(width: 300);
371 DrawSlidersDemo(gui);
377 if (gui.BeginMenu(
"Recursive"))
379 DrawMenuBarItems(gui, ref windowOpen);
385 if (gui.BeginMenu(
"Test"))
387 if (gui.BeginMenu(
"Same name submenu"))
393 gui.PushId(
"Next Menu");
395 if (gui.BeginMenu(
"Same name submenu"))
408 if (gui.Menu(
"Close"))
417 private static void DrawLayoutPage(ImGui gui)
421 gui.BeginHorizontal();
422 for (
int i = 0; i < 3; ++i)
424 gui.Button(
"Horizontal", ImSizeMode.Fit);
432 for (
int i = 0; i < 3; ++i)
434 gui.Button(
"Vertical", ImSizeMode.Fit);
441 var grid = gui.BeginGrid(5, gui.GetRowHeight());
442 for (
int i = 0; i < 12; ++i)
444 gui.TextAutoSize(Format(
"Grid cell ", i,
"0"), gui.GridNextCell(ref grid));
447 gui.EndGrid(in grid);
450 private static void DrawTablesPage(ImGui gui)
452 if (gui.BeginTreeNode(
"Simple"))
455 for (
int row = 0; row < 5; ++row)
458 for (
int col = 0; col < 4; ++col)
460 gui.TableNextColumn();
461 gui.Text(gui.Formatter.Concat(
"Hello At ", gui.Formatter.Format(col),
":", gui.Formatter.Format(row)));
466 gui.Separator(
"Resizable Columns");
468 gui.BeginTable(4, flags: ImTableFlag.ResizableColumns);
469 for (
int row = 0; row < 5; ++row)
472 for (
int col = 0; col < 4; ++col)
474 gui.TableNextColumn();
475 gui.Text(gui.Formatter.Concat(
"Hello At ", gui.Formatter.Format(col),
":", gui.Formatter.Format(row)), wrap:
true);
483 if (gui.BeginTreeNode(
"With Scroll Bars"))
485 gui.BeginTable(4, (gui.GetLayoutWidth(), 200));
486 for (
int row = 0; row < 12; ++row)
489 for (
int col = 0; col < 4; ++col)
491 gui.TableNextColumn();
492 gui.Text(gui.Formatter.Concat(
"Hello At ", gui.Formatter.Format(col),
":", gui.Formatter.Format(row)),
true);
500 if (gui.BeginTreeNode(
"Large Tables"))
502 NumEditWithLabel(gui, ref largeTableRows,
"Rows", min: 1, max: 1024 * 1024 * 4);
503 NumEditWithLabel(gui, ref largeTableColumns,
"Columns", min: 1, max: 4096);
504 NumEditWithLabel(gui, ref largeTableColumnSize,
"Col. Size", min: 50, max: 300);
506 gui.Checkbox(ref largeTableResizable,
"Resizable Columns");
507 gui.Checkbox(ref largeTableScrollable,
"Scrollable");
509 var size = largeTableScrollable ?
new ImSize(gui.GetLayoutWidth(), 300) : new ImSize(ImSizeMode.Auto);
510 var flags = largeTableResizable ? ImTableFlag.ResizableColumns : ImTableFlag.None;
512 ref var state = ref gui.BeginTable(largeTableColumns, size, flags);
514 gui.TableSetRowsHeight(gui.GetTextLineHeight() + gui.Style.Table.CellPadding.Vertical);
515 for (
int i = 0; i < largeTableColumns; ++i)
517 gui.TableSetColumnWidth(i, largeTableColumnSize);
520 var textSettings =
new ImTextSettings(gui.Style.Layout.TextSize,
new ImAlignment(0.5f, 0.5f), overflow: ImTextOverflow.Ellipsis);
521 var rowsRange = gui.TableGetVisibleRows(largeTableRows);
522 var colsRange = gui.TableGetVisibleColumns();
524 for (
int row = rowsRange.Min; row < rowsRange.Max; ++row)
526 gui.TableSetRow(row, ref state);
528 for (
int col = colsRange.Min; col < colsRange.Max; ++col)
530 gui.TableSetColumn(col, ref state);
531 gui.Text(gui.Formatter.Concat(gui.Formatter.Format(col),
"x", gui.Formatter.Format(row)), textSettings);
541 private static void NumEditWithLabel(ImGui gui, ref
int value, ReadOnlySpan<char> label,
int min,
int max)
543 gui.AddSpacingIfLayoutFrameNotEmpty();
544 gui.BeginHorizontal();
545 gui.Text(label, gui.Layout.AddRect(150, gui.GetRowHeight()));
546 gui.NumericEdit(ref value, min: min, max: max, flags: ImNumericEditFlag.PlusMinus);
550 private static void NumEditWithLabel(ImGui gui, ref
float value, ReadOnlySpan<char> label,
float min,
float max)
552 gui.AddSpacingIfLayoutFrameNotEmpty();
553 gui.BeginHorizontal();
554 gui.Text(label, gui.Layout.AddRect(150, gui.GetRowHeight()));
555 gui.NumericEdit(ref value, min: min, max: max, flags: ImNumericEditFlag.PlusMinus);
561 float mod(
float x,
float y)
563 return ((x % y) + y) % y;
567 .AddLayoutRectWithSpacing(gui.GetLayoutWidth(), gui.GetRowHeight() * 1.25f)
568 .WithPadding(left: bouncingBallSize / 2.0f, right: bouncingBallSize / 2.0f);
569 var dt = Time.unscaledDeltaTime * bouncingBallSpeed;
571 bouncingBallTime += dt;
573 for (
int i = 0; i < bouncingBallTrail; ++i)
575 var t = mod((bouncingBallTime + (i * 0.01f * bouncingBallSpeed)), 2.0f);
576 var x = t <= 1.0f ? t : 1 - (t - 1);
577 var y = 0.5f + Mathf.Sin((bouncingBallTime + (i * 0.01f * bouncingBallSpeed)) * Mathf.PI * 2) * 0.25f;
578 var p = bounds.GetPointAtNormalPosition(x, y);
579 var c = gui.Style.Text.Color.WithAlpha(Mathf.Pow((i + 1) / (
float)bouncingBallTrail, 6));
581 gui.Canvas.Circle(p, bouncingBallSize * 0.5f, c);
589 var label = current == 0 ?
"Nested Foldout" : Format(
"Nested Foldout ", current,
"0");
591 if (!gui.BeginFoldout(label))
601 else if (current == total)
605 gui.Text(
"Let's just stop here");
606 if (gui.Button(
"Reset"))
611 else if (gui.Button(
"Add one more"))
621 private static ReadOnlySpan<char> Format(ReadOnlySpan<char> prefix,
float value, ReadOnlySpan<char> format =
default)
623 var dst =
new Span<char>(formatBuffer);
625 value.TryFormat(dst[prefix.Length..], out var written, format);
626 return dst[..(prefix.Length + written)];