1 // dear imgui, v1.60 WIP
2 // (demo code)
3 
4 // Message to the person tempted to delete this file when integrating ImGui into their code base:
5 // Don't do it! Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to.
6 // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
7 // During development, you can call ImGui::ShowDemoWindow() in your code to learn about various features of ImGui. Have it wired in a debug menu!
8 // Removing this file from your project is hindering access to documentation for everyone in your team, likely leading you to poorer usage of the library.
9 // Note that you can #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h for the same effect.
10 // If you want to link core ImGui in your final builds but not those demo windows, #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h and those functions will be empty.
11 // In other situation, when you have ImGui available you probably want this to be available for reference and execution.
12 // Thank you,
13 // -Your beloved friend, imgui_demo.cpp (that you won't delete)
14 
15 // Message to beginner C/C++ programmers. About the meaning of 'static': in this demo code, we frequently we use 'static' variables inside functions.
16 // We do this as a way to gather code and data in the same place, just to make the demo code faster to read, faster to write, and use less code.
17 // A static variable persist across calls, so it is essentially like a global variable but declared inside the scope of the function.
18 // It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant or used in threads.
19 // This might be a pattern you occasionally want to use in your code, but most of the real data you would be editing is likely to be stored outside your function.
20 
21 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
22 #define _CRT_SECURE_NO_WARNINGS
23 #endif
24 
25 #include "imgui.h"
26 #include <ctype.h>                         // toupper, isprint
27 #include <math.h>                          // sqrtf, powf, cosf, sinf, floorf, ceilf
28 #include <stdio.h>                         // vsnprintf, sscanf, printf
29 #include <stdlib.h>                        // NULL, malloc, free, atoi
30 #if defined(_MSC_VER) && _MSC_VER <= 1500  // MSVC 2008 or earlier
31 #include <stddef.h>                        // intptr_t
32 #else
33 #include <stdint.h>  // intptr_t
34 #endif
35 
36 #ifdef _MSC_VER
37 #pragma warning(disable : 4996)  // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
38 #define snprintf _snprintf
39 #endif
40 #ifdef __clang__
41 #pragma clang diagnostic ignored "-Wold-style-cast"            // warning : use of old-style cast                              // yes, they are more terse.
42 #pragma clang diagnostic ignored "-Wdeprecated-declarations"   // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)
43 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"  // warning : cast to 'void *' from smaller integer type 'int'
44 #pragma clang diagnostic ignored "-Wformat-security"           // warning : warning: format string is not a string literal
45 #pragma clang diagnostic ignored "-Wexit-time-destructors"     // warning : declaration requires an exit-time destructor       // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
46 #if __has_warning("-Wreserved-id-macro")
47 #pragma clang diagnostic ignored "-Wreserved-id-macro"  // warning : macro name is a reserved identifier                //
48 #endif
49 #elif defined(__GNUC__)
50 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"  // warning: cast to pointer from integer of different size
51 #pragma GCC diagnostic ignored "-Wformat-security"      // warning : format string is not a string literal (potentially insecure)
52 #pragma GCC diagnostic ignored "-Wdouble-promotion"     // warning: implicit conversion from 'float' to 'double' when passing argument to function
53 #pragma GCC diagnostic ignored "-Wconversion"           // warning: conversion to 'xxxx' from 'xxxx' may alter its value
54 #if (__GNUC__ >= 6)
55 #pragma GCC diagnostic ignored "-Wmisleading-indentation"  // warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
56 #endif
57 #endif
58 
59 // Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n.
60 #ifdef _WIN32
61 #define IM_NEWLINE "\r\n"
62 #else
63 #define IM_NEWLINE "\n"
64 #endif
65 
66 #define IM_MAX(_A, _B) (((_A) >= (_B)) ? (_A) : (_B))
67 
68 //-----------------------------------------------------------------------------
69 // DEMO CODE
70 //-----------------------------------------------------------------------------
71 
72 #if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS)  // Obsolete name since 1.53, TEST->DEMO
73 #define IMGUI_DISABLE_DEMO_WINDOWS
74 #endif
75 
76 #if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
77 
78 static void ShowExampleAppConsole(bool* p_open);
79 static void ShowExampleAppLog(bool* p_open);
80 static void ShowExampleAppLayout(bool* p_open);
81 static void ShowExampleAppPropertyEditor(bool* p_open);
82 static void ShowExampleAppLongText(bool* p_open);
83 static void ShowExampleAppAutoResize(bool* p_open);
84 static void ShowExampleAppConstrainedResize(bool* p_open);
85 static void ShowExampleAppFixedOverlay(bool* p_open);
86 static void ShowExampleAppWindowTitles(bool* p_open);
87 static void ShowExampleAppCustomRendering(bool* p_open);
88 static void ShowExampleAppMainMenuBar();
89 static void ShowExampleMenuFile();
90 
ShowHelpMarker(const char * desc)91 static void ShowHelpMarker(const char* desc)
92 {
93 	ImGui::TextDisabled("(?)");
94 	if (ImGui::IsItemHovered())
95 	{
96 		ImGui::BeginTooltip();
97 		ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
98 		ImGui::TextUnformatted(desc);
99 		ImGui::PopTextWrapPos();
100 		ImGui::EndTooltip();
101 	}
102 }
103 
ShowUserGuide()104 void ImGui::ShowUserGuide()
105 {
106 	ImGui::BulletText("Double-click on title bar to collapse window.");
107 	ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents).");
108 	ImGui::BulletText("Click and drag on any empty space to move window.");
109 	ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
110 	ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
111 	if (ImGui::GetIO().FontAllowUserScaling)
112 		ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
113 	ImGui::BulletText("Mouse Wheel to scroll.");
114 	ImGui::BulletText("While editing text:\n");
115 	ImGui::Indent();
116 	ImGui::BulletText("Hold SHIFT or use mouse to select text.");
117 	ImGui::BulletText("CTRL+Left/Right to word jump.");
118 	ImGui::BulletText("CTRL+A or double-click to select all.");
119 	ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard.");
120 	ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
121 	ImGui::BulletText("ESCAPE to revert.");
122 	ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
123 	ImGui::Unindent();
124 }
125 
126 // Demonstrate most ImGui features (big function!)
ShowDemoWindow(bool * p_open)127 void ImGui::ShowDemoWindow(bool* p_open)
128 {
129 	// Examples apps
130 	static bool show_app_main_menu_bar = false;
131 	static bool show_app_console = false;
132 	static bool show_app_log = false;
133 	static bool show_app_layout = false;
134 	static bool show_app_property_editor = false;
135 	static bool show_app_long_text = false;
136 	static bool show_app_auto_resize = false;
137 	static bool show_app_constrained_resize = false;
138 	static bool show_app_fixed_overlay = false;
139 	static bool show_app_window_titles = false;
140 	static bool show_app_custom_rendering = false;
141 	static bool show_app_style_editor = false;
142 
143 	static bool show_app_metrics = false;
144 	static bool show_app_about = false;
145 
146 	if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
147 	if (show_app_console) ShowExampleAppConsole(&show_app_console);
148 	if (show_app_log) ShowExampleAppLog(&show_app_log);
149 	if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
150 	if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor);
151 	if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
152 	if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
153 	if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize);
154 	if (show_app_fixed_overlay) ShowExampleAppFixedOverlay(&show_app_fixed_overlay);
155 	if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles);
156 	if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);
157 
158 	if (show_app_metrics)
159 	{
160 		ImGui::ShowMetricsWindow(&show_app_metrics);
161 	}
162 	if (show_app_style_editor)
163 	{
164 		ImGui::Begin("Style Editor", &show_app_style_editor);
165 		ImGui::ShowStyleEditor();
166 		ImGui::End();
167 	}
168 	if (show_app_about)
169 	{
170 		ImGui::Begin("About Dear ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize);
171 		ImGui::Text("Dear ImGui, %s", ImGui::GetVersion());
172 		ImGui::Separator();
173 		ImGui::Text("By Omar Cornut and all dear imgui contributors.");
174 		ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
175 		ImGui::End();
176 	}
177 
178 	static bool no_titlebar = false;
179 	static bool no_scrollbar = false;
180 	static bool no_menu = false;
181 	static bool no_move = false;
182 	static bool no_resize = false;
183 	static bool no_collapse = false;
184 	static bool no_close = false;
185 	static bool no_nav = false;
186 
187 	// Demonstrate the various window flags. Typically you would just use the default.
188 	ImGuiWindowFlags window_flags = 0;
189 	if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
190 	if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
191 	if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar;
192 	if (no_move) window_flags |= ImGuiWindowFlags_NoMove;
193 	if (no_resize) window_flags |= ImGuiWindowFlags_NoResize;
194 	if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
195 	if (no_nav) window_flags |= ImGuiWindowFlags_NoNav;
196 	if (no_close) p_open = NULL;  // Don't pass our bool* to Begin
197 
198 	ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
199 	if (!ImGui::Begin("ImGui Demo", p_open, window_flags))
200 	{
201 		// Early out if the window is collapsed, as an optimization.
202 		ImGui::End();
203 		return;
204 	}
205 
206 	//ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);    // 2/3 of the space for widget and 1/3 for labels
207 	ImGui::PushItemWidth(-140);  // Right align, keep 140 pixels for labels
208 
209 	ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
210 
211 	// Menu
212 	if (ImGui::BeginMenuBar())
213 	{
214 		if (ImGui::BeginMenu("Menu"))
215 		{
216 			ShowExampleMenuFile();
217 			ImGui::EndMenu();
218 		}
219 		if (ImGui::BeginMenu("Examples"))
220 		{
221 			ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
222 			ImGui::MenuItem("Console", NULL, &show_app_console);
223 			ImGui::MenuItem("Log", NULL, &show_app_log);
224 			ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
225 			ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
226 			ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
227 			ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
228 			ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
229 			ImGui::MenuItem("Simple overlay", NULL, &show_app_fixed_overlay);
230 			ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
231 			ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
232 			ImGui::EndMenu();
233 		}
234 		if (ImGui::BeginMenu("Help"))
235 		{
236 			ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
237 			ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
238 			ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
239 			ImGui::EndMenu();
240 		}
241 		ImGui::EndMenuBar();
242 	}
243 
244 	ImGui::Spacing();
245 	if (ImGui::CollapsingHeader("Help"))
246 	{
247 		ImGui::TextWrapped("This window is being created by the ShowDemoWindow() function. Please refer to the code in imgui_demo.cpp for reference.\n\n");
248 		ImGui::Text("USER GUIDE:");
249 		ImGui::ShowUserGuide();
250 	}
251 
252 	if (ImGui::CollapsingHeader("Window options"))
253 	{
254 		ImGui::Checkbox("No titlebar", &no_titlebar);
255 		ImGui::SameLine(150);
256 		ImGui::Checkbox("No scrollbar", &no_scrollbar);
257 		ImGui::SameLine(300);
258 		ImGui::Checkbox("No menu", &no_menu);
259 		ImGui::Checkbox("No move", &no_move);
260 		ImGui::SameLine(150);
261 		ImGui::Checkbox("No resize", &no_resize);
262 		ImGui::SameLine(300);
263 		ImGui::Checkbox("No collapse", &no_collapse);
264 		ImGui::Checkbox("No close", &no_close);
265 		ImGui::SameLine(150);
266 		ImGui::Checkbox("No nav", &no_nav);
267 
268 		if (ImGui::TreeNode("Style"))
269 		{
270 			ImGui::ShowStyleEditor();
271 			ImGui::TreePop();
272 		}
273 
274 		if (ImGui::TreeNode("Capture/Logging"))
275 		{
276 			ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output directly to the log without a visual output.");
277 			ImGui::LogButtons();
278 			ImGui::TreePop();
279 		}
280 	}
281 
282 	if (ImGui::CollapsingHeader("Widgets"))
283 	{
284 		if (ImGui::TreeNode("Basic"))
285 		{
286 			static int clicked = 0;
287 			if (ImGui::Button("Button"))
288 				clicked++;
289 			if (clicked & 1)
290 			{
291 				ImGui::SameLine();
292 				ImGui::Text("Thanks for clicking me!");
293 			}
294 
295 			static bool check = true;
296 			ImGui::Checkbox("checkbox", &check);
297 
298 			static int e = 0;
299 			ImGui::RadioButton("radio a", &e, 0);
300 			ImGui::SameLine();
301 			ImGui::RadioButton("radio b", &e, 1);
302 			ImGui::SameLine();
303 			ImGui::RadioButton("radio c", &e, 2);
304 
305 			// Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
306 			for (int i = 0; i < 7; i++)
307 			{
308 				if (i > 0) ImGui::SameLine();
309 				ImGui::PushID(i);
310 				ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f));
311 				ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f));
312 				ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f));
313 				ImGui::Button("Click");
314 				ImGui::PopStyleColor(3);
315 				ImGui::PopID();
316 			}
317 
318 			ImGui::Text("Hover over me");
319 			if (ImGui::IsItemHovered())
320 				ImGui::SetTooltip("I am a tooltip");
321 
322 			ImGui::SameLine();
323 			ImGui::Text("- or me");
324 			if (ImGui::IsItemHovered())
325 			{
326 				ImGui::BeginTooltip();
327 				ImGui::Text("I am a fancy tooltip");
328 				static float arr[] = {0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f};
329 				ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
330 				ImGui::EndTooltip();
331 			}
332 
333 			// Testing ImGuiOnceUponAFrame helper.
334 			//static ImGuiOnceUponAFrame once;
335 			//for (int i = 0; i < 5; i++)
336 			//    if (once)
337 			//        ImGui::Text("This will be displayed only once.");
338 
339 			ImGui::Separator();
340 
341 			ImGui::LabelText("label", "Value");
342 
343 			{
344 				// Simplified one-liner Combo() API, using values packed in a single constant string
345 				static int current_item_1 = 1;
346 				ImGui::Combo("combo", &current_item_1, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
347 				//ImGui::Combo("combo w/ array of char*", &current_item_2_idx, items, IM_ARRAYSIZE(items));   // Combo using proper array. You can also pass a callback to retrieve array value, no need to create/copy an array just for that.
348 
349 				// General BeginCombo() API, you have full control over your selection data and display type
350 				const char* items[] = {"AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO", "PPPP", "QQQQQQQQQQ", "RRR", "SSSS"};
351 				static const char* current_item_2 = NULL;
352 				if (ImGui::BeginCombo("combo 2", current_item_2))  // The second parameter is the label previewed before opening the combo.
353 				{
354 					for (int n = 0; n < IM_ARRAYSIZE(items); n++)
355 					{
356 						bool is_selected = (current_item_2 == items[n]);  // You can store your selection however you want, outside or inside your objects
357 						if (ImGui::Selectable(items[n], is_selected))
358 							current_item_2 = items[n];
359 						if (is_selected)
360 							ImGui::SetItemDefaultFocus();  // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch)
361 					}
362 					ImGui::EndCombo();
363 				}
364 			}
365 
366 			{
367 				static char str0[128] = "Hello, world!";
368 				static int i0 = 123;
369 				static float f0 = 0.001f;
370 				ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
371 				ImGui::SameLine();
372 				ShowHelpMarker(
373 					"Hold SHIFT or use mouse to select text.\n"
374 					"CTRL+Left/Right to word jump.\n"
375 					"CTRL+A or double-click to select all.\n"
376 					"CTRL+X,CTRL+C,CTRL+V clipboard.\n"
377 					"CTRL+Z,CTRL+Y undo/redo.\n"
378 					"ESCAPE to revert.\n");
379 
380 				ImGui::InputInt("input int", &i0);
381 				ImGui::SameLine();
382 				ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n  e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
383 
384 				ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);
385 
386 				static float vec4a[4] = {0.10f, 0.20f, 0.30f, 0.44f};
387 				ImGui::InputFloat3("input float3", vec4a);
388 			}
389 
390 			{
391 				static int i1 = 50, i2 = 42;
392 				ImGui::DragInt("drag int", &i1, 1);
393 				ImGui::SameLine();
394 				ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
395 
396 				ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%.0f%%");
397 
398 				static float f1 = 1.00f, f2 = 0.0067f;
399 				ImGui::DragFloat("drag float", &f1, 0.005f);
400 				ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
401 			}
402 
403 			{
404 				static int i1 = 0;
405 				ImGui::SliderInt("slider int", &i1, -1, 3);
406 				ImGui::SameLine();
407 				ShowHelpMarker("CTRL+click to input value.");
408 
409 				static float f1 = 0.123f, f2 = 0.0f;
410 				ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
411 				ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f);
412 				static float angle = 0.0f;
413 				ImGui::SliderAngle("slider angle", &angle);
414 			}
415 
416 			static float col1[3] = {1.0f, 0.0f, 0.2f};
417 			static float col2[4] = {0.4f, 0.7f, 0.0f, 0.5f};
418 			ImGui::ColorEdit3("color 1", col1);
419 			ImGui::SameLine();
420 			ShowHelpMarker("Click on the colored square to open a color picker.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");
421 
422 			ImGui::ColorEdit4("color 2", col2);
423 
424 			const char* listbox_items[] = {"Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon"};
425 			static int listbox_item_current = 1;
426 			ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
427 
428 			//static int listbox_item_current2 = 2;
429 			//ImGui::PushItemWidth(-1);
430 			//ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
431 			//ImGui::PopItemWidth();
432 
433 			ImGui::TreePop();
434 		}
435 
436 		if (ImGui::TreeNode("Trees"))
437 		{
438 			if (ImGui::TreeNode("Basic trees"))
439 			{
440 				for (int i = 0; i < 5; i++)
441 					if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
442 					{
443 						ImGui::Text("blah blah");
444 						ImGui::SameLine();
445 						if (ImGui::SmallButton("button"))
446 						{
447 						};
448 						ImGui::TreePop();
449 					}
450 				ImGui::TreePop();
451 			}
452 
453 			if (ImGui::TreeNode("Advanced, with Selectable nodes"))
454 			{
455 				ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
456 				static bool align_label_with_current_x_position = false;
457 				ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
458 				ImGui::Text("Hello!");
459 				if (align_label_with_current_x_position)
460 					ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
461 
462 				static int selection_mask = (1 << 2);                                        // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.
463 				int node_clicked = -1;                                                       // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc.
464 				ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize() * 3);  // Increase spacing to differentiate leaves from expanded contents.
465 				for (int i = 0; i < 6; i++)
466 				{
467 					// Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
468 					ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);
469 					if (i < 3)
470 					{
471 						// Node
472 						bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
473 						if (ImGui::IsItemClicked())
474 							node_clicked = i;
475 						if (node_open)
476 						{
477 							ImGui::Text("Blah blah\nBlah Blah");
478 							ImGui::TreePop();
479 						}
480 					}
481 					else
482 					{
483 						// Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text().
484 						node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen;  // ImGuiTreeNodeFlags_Bullet
485 						ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
486 						if (ImGui::IsItemClicked())
487 							node_clicked = i;
488 					}
489 				}
490 				if (node_clicked != -1)
491 				{
492 					// Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
493 					if (ImGui::GetIO().KeyCtrl)
494 						selection_mask ^= (1 << node_clicked);  // CTRL+click to toggle
495 					else                                        //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection
496 						selection_mask = (1 << node_clicked);   // Click to single-select
497 				}
498 				ImGui::PopStyleVar();
499 				if (align_label_with_current_x_position)
500 					ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
501 				ImGui::TreePop();
502 			}
503 			ImGui::TreePop();
504 		}
505 
506 		if (ImGui::TreeNode("Collapsing Headers"))
507 		{
508 			static bool closable_group = true;
509 			ImGui::Checkbox("Enable extra group", &closable_group);
510 			if (ImGui::CollapsingHeader("Header"))
511 			{
512 				ImGui::Text("IsItemHovered: %d", IsItemHovered());
513 				for (int i = 0; i < 5; i++)
514 					ImGui::Text("Some content %d", i);
515 			}
516 			if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
517 			{
518 				ImGui::Text("IsItemHovered: %d", IsItemHovered());
519 				for (int i = 0; i < 5; i++)
520 					ImGui::Text("More content %d", i);
521 			}
522 			ImGui::TreePop();
523 		}
524 
525 		if (ImGui::TreeNode("Bullets"))
526 		{
527 			ImGui::BulletText("Bullet point 1");
528 			ImGui::BulletText("Bullet point 2\nOn multiple lines");
529 			ImGui::Bullet();
530 			ImGui::Text("Bullet point 3 (two calls)");
531 			ImGui::Bullet();
532 			ImGui::SmallButton("Button");
533 			ImGui::TreePop();
534 		}
535 
536 		if (ImGui::TreeNode("Text"))
537 		{
538 			if (ImGui::TreeNode("Colored Text"))
539 			{
540 				// Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
541 				ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink");
542 				ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow");
543 				ImGui::TextDisabled("Disabled");
544 				ImGui::SameLine();
545 				ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
546 				ImGui::TreePop();
547 			}
548 
549 			if (ImGui::TreeNode("Word Wrapping"))
550 			{
551 				// Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
552 				ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages.");
553 				ImGui::Spacing();
554 
555 				static float wrap_width = 200.0f;
556 				ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
557 
558 				ImGui::Text("Test paragraph 1:");
559 				ImVec2 pos = ImGui::GetCursorScreenPos();
560 				ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255, 0, 255, 255));
561 				ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
562 				ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width);
563 				ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
564 				ImGui::PopTextWrapPos();
565 
566 				ImGui::Text("Test paragraph 2:");
567 				pos = ImGui::GetCursorScreenPos();
568 				ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255, 0, 255, 255));
569 				ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
570 				ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee   ffffffff. gggggggg!hhhhhhhh");
571 				ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
572 				ImGui::PopTextWrapPos();
573 
574 				ImGui::TreePop();
575 			}
576 
577 			if (ImGui::TreeNode("UTF-8 Text"))
578 			{
579 				// UTF-8 test with Japanese characters
580 				// (needs a suitable font, try Arial Unicode or M+ fonts http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html)
581 				// - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
582 				// - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. Visual Studio save your file as 'UTF-8 without signature')
583 				// - HOWEVER, FOR THIS DEMO FILE, BECAUSE WE WANT TO SUPPORT COMPILER, WE ARE *NOT* INCLUDING RAW UTF-8 CHARACTERS IN THIS SOURCE FILE.
584 				//   Instead we are encoding a few string with hexadecimal constants. Don't do this in your application!
585 				// Note that characters values are preserved even by InputText() if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.
586 				ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges.");
587 				ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
588 				ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
589 				static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";  // "nihongo"
590 				ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
591 				ImGui::TreePop();
592 			}
593 			ImGui::TreePop();
594 		}
595 
596 		if (ImGui::TreeNode("Images"))
597 		{
598 			ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!");
599 			ImGuiIO& io = ImGui::GetIO();
600 
601 			// Here we are grabbing the font texture because that's the only one we have access to inside the demo code.
602 			// Remember that ImTextureID is just storage for whatever you want it to be, it is essentially a value that will be passed to the render function inside the ImDrawCmd structure.
603 			// If you use one of the default imgui_impl_XXXX.cpp renderer, they all have comments at the top of their file to specify what they expect to be stored in ImTextureID.
604 			// (for example, the imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer. The imgui_impl_glfw_gl3.cpp renderer expect a GLuint OpenGL texture identifier etc.)
605 			// If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers to ImGui::Image(), and gather width/height through your own functions, etc.
606 			// Using ShowMetricsWindow() as a "debugger" to inspect the draw data that are being passed to your render will help you debug issues if you are confused about this.
607 			// Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
608 			ImTextureID my_tex_id = io.Fonts->TexID;
609 			float my_tex_w = (float)io.Fonts->TexWidth;
610 			float my_tex_h = (float)io.Fonts->TexHeight;
611 
612 			ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
613 			ImVec2 pos = ImGui::GetCursorScreenPos();
614 			ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), ImVec2(0, 0), ImVec2(1, 1), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128));
615 			if (ImGui::IsItemHovered())
616 			{
617 				ImGui::BeginTooltip();
618 				float focus_sz = 32.0f;
619 				float focus_x = io.MousePos.x - pos.x - focus_sz * 0.5f;
620 				if (focus_x < 0.0f)
621 					focus_x = 0.0f;
622 				else if (focus_x > my_tex_w - focus_sz)
623 					focus_x = my_tex_w - focus_sz;
624 				float focus_y = io.MousePos.y - pos.y - focus_sz * 0.5f;
625 				if (focus_y < 0.0f)
626 					focus_y = 0.0f;
627 				else if (focus_y > my_tex_h - focus_sz)
628 					focus_y = my_tex_h - focus_sz;
629 				ImGui::Text("Min: (%.2f, %.2f)", focus_x, focus_y);
630 				ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz);
631 				ImVec2 uv0 = ImVec2((focus_x) / my_tex_w, (focus_y) / my_tex_h);
632 				ImVec2 uv1 = ImVec2((focus_x + focus_sz) / my_tex_w, (focus_y + focus_sz) / my_tex_h);
633 				ImGui::Image(my_tex_id, ImVec2(128, 128), uv0, uv1, ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128));
634 				ImGui::EndTooltip();
635 			}
636 			ImGui::TextWrapped("And now some textured buttons..");
637 			static int pressed_count = 0;
638 			for (int i = 0; i < 8; i++)
639 			{
640 				ImGui::PushID(i);
641 				int frame_padding = -1 + i;  // -1 = uses default padding
642 				if (ImGui::ImageButton(my_tex_id, ImVec2(32, 32), ImVec2(0, 0), ImVec2(32.0f / my_tex_w, 32 / my_tex_h), frame_padding, ImColor(0, 0, 0, 255)))
643 					pressed_count += 1;
644 				ImGui::PopID();
645 				ImGui::SameLine();
646 			}
647 			ImGui::NewLine();
648 			ImGui::Text("Pressed %d times.", pressed_count);
649 			ImGui::TreePop();
650 		}
651 
652 		if (ImGui::TreeNode("Selectables"))
653 		{
654 			// Selectable() has 2 overloads:
655 			// - The one taking "bool selected" as a read-only selection information. When Selectable() has been clicked is returns true and you can alter selection state accordingly.
656 			// - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
657 			// The earlier is more flexible, as in real application your selection may be stored in a different manner (in flags within objects, as an external list, etc).
658 			if (ImGui::TreeNode("Basic"))
659 			{
660 				static bool selection[5] = {false, true, false, false, false};
661 				ImGui::Selectable("1. I am selectable", &selection[0]);
662 				ImGui::Selectable("2. I am selectable", &selection[1]);
663 				ImGui::Text("3. I am not selectable");
664 				ImGui::Selectable("4. I am selectable", &selection[3]);
665 				if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick))
666 					if (ImGui::IsMouseDoubleClicked(0))
667 						selection[4] = !selection[4];
668 				ImGui::TreePop();
669 			}
670 			if (ImGui::TreeNode("Selection State: Single Selection"))
671 			{
672 				static int selected = -1;
673 				for (int n = 0; n < 5; n++)
674 				{
675 					char buf[32];
676 					sprintf(buf, "Object %d", n);
677 					if (ImGui::Selectable(buf, selected == n))
678 						selected = n;
679 				}
680 				ImGui::TreePop();
681 			}
682 			if (ImGui::TreeNode("Selection State: Multiple Selection"))
683 			{
684 				ShowHelpMarker("Hold CTRL and click to select multiple items.");
685 				static bool selection[5] = {false, false, false, false, false};
686 				for (int n = 0; n < 5; n++)
687 				{
688 					char buf[32];
689 					sprintf(buf, "Object %d", n);
690 					if (ImGui::Selectable(buf, selection[n]))
691 					{
692 						if (!ImGui::GetIO().KeyCtrl)  // Clear selection when CTRL is not held
693 							memset(selection, 0, sizeof(selection));
694 						selection[n] ^= 1;
695 					}
696 				}
697 				ImGui::TreePop();
698 			}
699 			if (ImGui::TreeNode("Rendering more text into the same line"))
700 			{
701 				// Using the Selectable() override that takes "bool* p_selected" parameter and toggle your booleans automatically.
702 				static bool selected[3] = {false, false, false};
703 				ImGui::Selectable("main.c", &selected[0]);
704 				ImGui::SameLine(300);
705 				ImGui::Text(" 2,345 bytes");
706 				ImGui::Selectable("Hello.cpp", &selected[1]);
707 				ImGui::SameLine(300);
708 				ImGui::Text("12,345 bytes");
709 				ImGui::Selectable("Hello.h", &selected[2]);
710 				ImGui::SameLine(300);
711 				ImGui::Text(" 2,345 bytes");
712 				ImGui::TreePop();
713 			}
714 			if (ImGui::TreeNode("In columns"))
715 			{
716 				ImGui::Columns(3, NULL, false);
717 				static bool selected[16] = {0};
718 				for (int i = 0; i < 16; i++)
719 				{
720 					char label[32];
721 					sprintf(label, "Item %d", i);
722 					if (ImGui::Selectable(label, &selected[i]))
723 					{
724 					}
725 					ImGui::NextColumn();
726 				}
727 				ImGui::Columns(1);
728 				ImGui::TreePop();
729 			}
730 			if (ImGui::TreeNode("Grid"))
731 			{
732 				static bool selected[16] = {true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true};
733 				for (int i = 0; i < 16; i++)
734 				{
735 					ImGui::PushID(i);
736 					if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50, 50)))
737 					{
738 						int x = i % 4, y = i / 4;
739 						if (x > 0) selected[i - 1] ^= 1;
740 						if (x < 3) selected[i + 1] ^= 1;
741 						if (y > 0) selected[i - 4] ^= 1;
742 						if (y < 3) selected[i + 4] ^= 1;
743 					}
744 					if ((i % 4) < 3) ImGui::SameLine();
745 					ImGui::PopID();
746 				}
747 				ImGui::TreePop();
748 			}
749 			ImGui::TreePop();
750 		}
751 
752 		if (ImGui::TreeNode("Filtered Text Input"))
753 		{
754 			static char buf1[64] = "";
755 			ImGui::InputText("default", buf1, 64);
756 			static char buf2[64] = "";
757 			ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
758 			static char buf3[64] = "";
759 			ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
760 			static char buf4[64] = "";
761 			ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
762 			static char buf5[64] = "";
763 			ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
764 			struct TextFilters
765 			{
766 				static int FilterImGuiLetters(ImGuiTextEditCallbackData* data)
767 				{
768 					if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0;
769 					return 1;
770 				}
771 			};
772 			static char buf6[64] = "";
773 			ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
774 
775 			ImGui::Text("Password input");
776 			static char bufpass[64] = "password123";
777 			ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
778 			ImGui::SameLine();
779 			ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
780 			ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
781 
782 			ImGui::TreePop();
783 		}
784 
785 		if (ImGui::TreeNode("Multi-line Text Input"))
786 		{
787 			static bool read_only = false;
788 			static char text[1024 * 16] =
789 				"/*\n"
790 				" The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
791 				" the hexadecimal encoding of one offending instruction,\n"
792 				" more formally, the invalid operand with locked CMPXCHG8B\n"
793 				" instruction bug, is a design flaw in the majority of\n"
794 				" Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
795 				" processors (all in the P5 microarchitecture).\n"
796 				"*/\n\n"
797 				"label:\n"
798 				"\tlock cmpxchg8b eax\n";
799 
800 			ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
801 			ImGui::Checkbox("Read-only", &read_only);
802 			ImGui::PopStyleVar();
803 			ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0));
804 			ImGui::TreePop();
805 		}
806 
807 		if (ImGui::TreeNode("Plots widgets"))
808 		{
809 			static bool animate = true;
810 			ImGui::Checkbox("Animate", &animate);
811 
812 			static float arr[] = {0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f};
813 			ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
814 
815 			// Create a dummy array of contiguous float values to plot
816 			// Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter.
817 			static float values[90] = {0};
818 			static int values_offset = 0;
819 			static float refresh_time = 0.0f;
820 			if (!animate || refresh_time == 0.0f)
821 				refresh_time = ImGui::GetTime();
822 			while (refresh_time < ImGui::GetTime())  // Create dummy data at fixed 60 hz rate for the demo
823 			{
824 				static float phase = 0.0f;
825 				values[values_offset] = cosf(phase);
826 				values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
827 				phase += 0.10f * values_offset;
828 				refresh_time += 1.0f / 60.0f;
829 			}
830 			ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0, 80));
831 			ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80));
832 
833 			// Use functions to generate output
834 			// FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count.
835 			struct Funcs
836 			{
837 				static float Sin(void*, int i) { return sinf(i * 0.1f); }
838 				static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
839 			};
840 			static int func_type = 0, display_count = 70;
841 			ImGui::Separator();
842 			ImGui::PushItemWidth(100);
843 			ImGui::Combo("func", &func_type, "Sin\0Saw\0");
844 			ImGui::PopItemWidth();
845 			ImGui::SameLine();
846 			ImGui::SliderInt("Sample count", &display_count, 1, 400);
847 			float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
848 			ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
849 			ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
850 			ImGui::Separator();
851 
852 			// Animate a simple progress bar
853 			static float progress = 0.0f, progress_dir = 1.0f;
854 			if (animate)
855 			{
856 				progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
857 				if (progress >= +1.1f)
858 				{
859 					progress = +1.1f;
860 					progress_dir *= -1.0f;
861 				}
862 				if (progress <= -0.1f)
863 				{
864 					progress = -0.1f;
865 					progress_dir *= -1.0f;
866 				}
867 			}
868 
869 			// Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
870 			ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
871 			ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
872 			ImGui::Text("Progress Bar");
873 
874 			float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
875 			char buf[32];
876 			sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
877 			ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
878 			ImGui::TreePop();
879 		}
880 
881 		if (ImGui::TreeNode("Color/Picker Widgets"))
882 		{
883 			static ImVec4 color = ImColor(114, 144, 154, 200);
884 
885 			static bool alpha_preview = true;
886 			static bool alpha_half_preview = false;
887 			static bool options_menu = true;
888 			static bool hdr = false;
889 			ImGui::Checkbox("With Alpha Preview", &alpha_preview);
890 			ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
891 			ImGui::Checkbox("With Options Menu", &options_menu);
892 			ImGui::SameLine();
893 			ShowHelpMarker("Right-click on the individual color widget to show options.");
894 			ImGui::Checkbox("With HDR", &hdr);
895 			ImGui::SameLine();
896 			ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
897 			int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
898 
899 			ImGui::Text("Color widget:");
900 			ImGui::SameLine();
901 			ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
902 			ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
903 
904 			ImGui::Text("Color widget HSV with Alpha:");
905 			ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags);
906 
907 			ImGui::Text("Color widget with Float Display:");
908 			ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
909 
910 			ImGui::Text("Color button with Picker:");
911 			ImGui::SameLine();
912 			ShowHelpMarker("With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\nWith the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only be used for the tooltip and picker popup.");
913 			ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
914 
915 			ImGui::Text("Color button with Custom Picker Popup:");
916 
917 			// Generate a dummy palette
918 			static bool saved_palette_inited = false;
919 			static ImVec4 saved_palette[32];
920 			if (!saved_palette_inited)
921 				for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
922 				{
923 					ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
924 					saved_palette[n].w = 1.0f;  // Alpha
925 				}
926 			saved_palette_inited = true;
927 
928 			static ImVec4 backup_color;
929 			bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
930 			ImGui::SameLine();
931 			open_popup |= ImGui::Button("Palette");
932 			if (open_popup)
933 			{
934 				ImGui::OpenPopup("mypicker");
935 				backup_color = color;
936 			}
937 			if (ImGui::BeginPopup("mypicker"))
938 			{
939 				// FIXME: Adding a drag and drop example here would be perfect!
940 				ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
941 				ImGui::Separator();
942 				ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
943 				ImGui::SameLine();
944 				ImGui::BeginGroup();
945 				ImGui::Text("Current");
946 				ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40));
947 				ImGui::Text("Previous");
948 				if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)))
949 					color = backup_color;
950 				ImGui::Separator();
951 				ImGui::Text("Palette");
952 				for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
953 				{
954 					ImGui::PushID(n);
955 					if ((n % 8) != 0)
956 						ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
957 					if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20)))
958 						color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w);  // Preserve alpha!
959 
960 					if (ImGui::BeginDragDropTarget())
961 					{
962 						if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
963 							memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
964 						if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
965 							memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
966 						EndDragDropTarget();
967 					}
968 
969 					ImGui::PopID();
970 				}
971 				ImGui::EndGroup();
972 				ImGui::EndPopup();
973 			}
974 
975 			ImGui::Text("Color button only:");
976 			ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80, 80));
977 
978 			ImGui::Text("Color picker:");
979 			static bool alpha = true;
980 			static bool alpha_bar = true;
981 			static bool side_preview = true;
982 			static bool ref_color = false;
983 			static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
984 			static int inputs_mode = 2;
985 			static int picker_mode = 0;
986 			ImGui::Checkbox("With Alpha", &alpha);
987 			ImGui::Checkbox("With Alpha Bar", &alpha_bar);
988 			ImGui::Checkbox("With Side Preview", &side_preview);
989 			if (side_preview)
990 			{
991 				ImGui::SameLine();
992 				ImGui::Checkbox("With Ref Color", &ref_color);
993 				if (ref_color)
994 				{
995 					ImGui::SameLine();
996 					ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
997 				}
998 			}
999 			ImGui::Combo("Inputs Mode", &inputs_mode, "All Inputs\0No Inputs\0RGB Input\0HSV Input\0HEX Input\0");
1000 			ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
1001 			ImGui::SameLine();
1002 			ShowHelpMarker("User can right-click the picker to change mode.");
1003 			ImGuiColorEditFlags flags = misc_flags;
1004 			if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha;  // This is by default if you call ColorPicker3() instead of ColorPicker4()
1005 			if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
1006 			if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
1007 			if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
1008 			if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
1009 			if (inputs_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;
1010 			if (inputs_mode == 2) flags |= ImGuiColorEditFlags_RGB;
1011 			if (inputs_mode == 3) flags |= ImGuiColorEditFlags_HSV;
1012 			if (inputs_mode == 4) flags |= ImGuiColorEditFlags_HEX;
1013 			ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
1014 
1015 			ImGui::Text("Programmatically set defaults/options:");
1016 			ImGui::SameLine();
1017 			ShowHelpMarker("SetColorEditOptions() is designed to allow you to set boot-time default.\nWe don't have Push/Pop functions because you can force options on a per-widget basis if needed, and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid encouraging you to persistently save values that aren't forward-compatible.");
1018 			if (ImGui::Button("Uint8 + HSV"))
1019 				ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HSV);
1020 			ImGui::SameLine();
1021 			if (ImGui::Button("Float + HDR"))
1022 				ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_RGB);
1023 
1024 			ImGui::TreePop();
1025 		}
1026 
1027 		if (ImGui::TreeNode("Range Widgets"))
1028 		{
1029 			static float begin = 10, end = 90;
1030 			static int begin_i = 100, end_i = 1000;
1031 			ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%");
1032 			ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %.0f units", "Max: %.0f units");
1033 			ImGui::TreePop();
1034 		}
1035 
1036 		if (ImGui::TreeNode("Multi-component Widgets"))
1037 		{
1038 			static float vec4f[4] = {0.10f, 0.20f, 0.30f, 0.44f};
1039 			static int vec4i[4] = {1, 5, 100, 255};
1040 
1041 			ImGui::InputFloat2("input float2", vec4f);
1042 			ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
1043 			ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
1044 			ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
1045 			ImGui::InputInt2("input int2", vec4i);
1046 			ImGui::SliderInt2("slider int2", vec4i, 0, 255);
1047 			ImGui::Spacing();
1048 
1049 			ImGui::InputFloat3("input float3", vec4f);
1050 			ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
1051 			ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
1052 			ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
1053 			ImGui::InputInt3("input int3", vec4i);
1054 			ImGui::SliderInt3("slider int3", vec4i, 0, 255);
1055 			ImGui::Spacing();
1056 
1057 			ImGui::InputFloat4("input float4", vec4f);
1058 			ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
1059 			ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
1060 			ImGui::InputInt4("input int4", vec4i);
1061 			ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
1062 			ImGui::SliderInt4("slider int4", vec4i, 0, 255);
1063 
1064 			ImGui::TreePop();
1065 		}
1066 
1067 		if (ImGui::TreeNode("Vertical Sliders"))
1068 		{
1069 			const float spacing = 4;
1070 			ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
1071 
1072 			static int int_value = 0;
1073 			ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
1074 			ImGui::SameLine();
1075 
1076 			static float values[7] = {0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f};
1077 			ImGui::PushID("set1");
1078 			for (int i = 0; i < 7; i++)
1079 			{
1080 				if (i > 0) ImGui::SameLine();
1081 				ImGui::PushID(i);
1082 				ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f));
1083 				ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f));
1084 				ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f));
1085 				ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f));
1086 				ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, "");
1087 				if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1088 					ImGui::SetTooltip("%.3f", values[i]);
1089 				ImGui::PopStyleColor(4);
1090 				ImGui::PopID();
1091 			}
1092 			ImGui::PopID();
1093 
1094 			ImGui::SameLine();
1095 			ImGui::PushID("set2");
1096 			static float values2[4] = {0.20f, 0.80f, 0.40f, 0.25f};
1097 			const int rows = 3;
1098 			const ImVec2 small_slider_size(18, (160.0f - (rows - 1) * spacing) / rows);
1099 			for (int nx = 0; nx < 4; nx++)
1100 			{
1101 				if (nx > 0) ImGui::SameLine();
1102 				ImGui::BeginGroup();
1103 				for (int ny = 0; ny < rows; ny++)
1104 				{
1105 					ImGui::PushID(nx * rows + ny);
1106 					ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
1107 					if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1108 						ImGui::SetTooltip("%.3f", values2[nx]);
1109 					ImGui::PopID();
1110 				}
1111 				ImGui::EndGroup();
1112 			}
1113 			ImGui::PopID();
1114 
1115 			ImGui::SameLine();
1116 			ImGui::PushID("set3");
1117 			for (int i = 0; i < 4; i++)
1118 			{
1119 				if (i > 0) ImGui::SameLine();
1120 				ImGui::PushID(i);
1121 				ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
1122 				ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
1123 				ImGui::PopStyleVar();
1124 				ImGui::PopID();
1125 			}
1126 			ImGui::PopID();
1127 			ImGui::PopStyleVar();
1128 			ImGui::TreePop();
1129 		}
1130 	}
1131 
1132 	if (ImGui::CollapsingHeader("Layout"))
1133 	{
1134 		if (ImGui::TreeNode("Child regions"))
1135 		{
1136 			static bool disable_mouse_wheel = false;
1137 			static bool disable_menu = false;
1138 			ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
1139 			ImGui::Checkbox("Disable Menu", &disable_menu);
1140 
1141 			static int line = 50;
1142 			bool goto_line = ImGui::Button("Goto");
1143 			ImGui::SameLine();
1144 			ImGui::PushItemWidth(100);
1145 			goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
1146 			ImGui::PopItemWidth();
1147 
1148 			// Child 1: no border, enable horizontal scrollbar
1149 			{
1150 				ImGui::BeginChild("Child1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 300), false, ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0));
1151 				for (int i = 0; i < 100; i++)
1152 				{
1153 					ImGui::Text("%04d: scrollable region", i);
1154 					if (goto_line && line == i)
1155 						ImGui::SetScrollHere();
1156 				}
1157 				if (goto_line && line >= 100)
1158 					ImGui::SetScrollHere();
1159 				ImGui::EndChild();
1160 			}
1161 
1162 			ImGui::SameLine();
1163 
1164 			// Child 2: rounded border
1165 			{
1166 				ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
1167 				ImGui::BeginChild("Child2", ImVec2(0, 300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar));
1168 				if (!disable_menu && ImGui::BeginMenuBar())
1169 				{
1170 					if (ImGui::BeginMenu("Menu"))
1171 					{
1172 						ShowExampleMenuFile();
1173 						ImGui::EndMenu();
1174 					}
1175 					ImGui::EndMenuBar();
1176 				}
1177 				ImGui::Columns(2);
1178 				for (int i = 0; i < 100; i++)
1179 				{
1180 					if (i == 50)
1181 						ImGui::NextColumn();
1182 					char buf[32];
1183 					sprintf(buf, "%08x", i * 5731);
1184 					ImGui::Button(buf, ImVec2(-1.0f, 0.0f));
1185 				}
1186 				ImGui::EndChild();
1187 				ImGui::PopStyleVar();
1188 			}
1189 
1190 			ImGui::TreePop();
1191 		}
1192 
1193 		if (ImGui::TreeNode("Widgets Width"))
1194 		{
1195 			static float f = 0.0f;
1196 			ImGui::Text("PushItemWidth(100)");
1197 			ImGui::SameLine();
1198 			ShowHelpMarker("Fixed width.");
1199 			ImGui::PushItemWidth(100);
1200 			ImGui::DragFloat("float##1", &f);
1201 			ImGui::PopItemWidth();
1202 
1203 			ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
1204 			ImGui::SameLine();
1205 			ShowHelpMarker("Half of window width.");
1206 			ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
1207 			ImGui::DragFloat("float##2", &f);
1208 			ImGui::PopItemWidth();
1209 
1210 			ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
1211 			ImGui::SameLine();
1212 			ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
1213 			ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
1214 			ImGui::DragFloat("float##3", &f);
1215 			ImGui::PopItemWidth();
1216 
1217 			ImGui::Text("PushItemWidth(-100)");
1218 			ImGui::SameLine();
1219 			ShowHelpMarker("Align to right edge minus 100");
1220 			ImGui::PushItemWidth(-100);
1221 			ImGui::DragFloat("float##4", &f);
1222 			ImGui::PopItemWidth();
1223 
1224 			ImGui::Text("PushItemWidth(-1)");
1225 			ImGui::SameLine();
1226 			ShowHelpMarker("Align to right edge");
1227 			ImGui::PushItemWidth(-1);
1228 			ImGui::DragFloat("float##5", &f);
1229 			ImGui::PopItemWidth();
1230 
1231 			ImGui::TreePop();
1232 		}
1233 
1234 		if (ImGui::TreeNode("Basic Horizontal Layout"))
1235 		{
1236 			ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
1237 
1238 			// Text
1239 			ImGui::Text("Two items: Hello");
1240 			ImGui::SameLine();
1241 			ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor");
1242 
1243 			// Adjust spacing
1244 			ImGui::Text("More spacing: Hello");
1245 			ImGui::SameLine(0, 20);
1246 			ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor");
1247 
1248 			// Button
1249 			ImGui::AlignTextToFramePadding();
1250 			ImGui::Text("Normal buttons");
1251 			ImGui::SameLine();
1252 			ImGui::Button("Banana");
1253 			ImGui::SameLine();
1254 			ImGui::Button("Apple");
1255 			ImGui::SameLine();
1256 			ImGui::Button("Corniflower");
1257 
1258 			// Button
1259 			ImGui::Text("Small buttons");
1260 			ImGui::SameLine();
1261 			ImGui::SmallButton("Like this one");
1262 			ImGui::SameLine();
1263 			ImGui::Text("can fit within a text block.");
1264 
1265 			// Aligned to arbitrary position. Easy/cheap column.
1266 			ImGui::Text("Aligned");
1267 			ImGui::SameLine(150);
1268 			ImGui::Text("x=150");
1269 			ImGui::SameLine(300);
1270 			ImGui::Text("x=300");
1271 			ImGui::Text("Aligned");
1272 			ImGui::SameLine(150);
1273 			ImGui::SmallButton("x=150");
1274 			ImGui::SameLine(300);
1275 			ImGui::SmallButton("x=300");
1276 
1277 			// Checkbox
1278 			static bool c1 = false, c2 = false, c3 = false, c4 = false;
1279 			ImGui::Checkbox("My", &c1);
1280 			ImGui::SameLine();
1281 			ImGui::Checkbox("Tailor", &c2);
1282 			ImGui::SameLine();
1283 			ImGui::Checkbox("Is", &c3);
1284 			ImGui::SameLine();
1285 			ImGui::Checkbox("Rich", &c4);
1286 
1287 			// Various
1288 			static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
1289 			ImGui::PushItemWidth(80);
1290 			const char* items[] = {"AAAA", "BBBB", "CCCC", "DDDD"};
1291 			static int item = -1;
1292 			ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items));
1293 			ImGui::SameLine();
1294 			ImGui::SliderFloat("X", &f0, 0.0f, 5.0f);
1295 			ImGui::SameLine();
1296 			ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f);
1297 			ImGui::SameLine();
1298 			ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
1299 			ImGui::PopItemWidth();
1300 
1301 			ImGui::PushItemWidth(80);
1302 			ImGui::Text("Lists:");
1303 			static int selection[4] = {0, 1, 2, 3};
1304 			for (int i = 0; i < 4; i++)
1305 			{
1306 				if (i > 0) ImGui::SameLine();
1307 				ImGui::PushID(i);
1308 				ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
1309 				ImGui::PopID();
1310 				//if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
1311 			}
1312 			ImGui::PopItemWidth();
1313 
1314 			// Dummy
1315 			ImVec2 sz(30, 30);
1316 			ImGui::Button("A", sz);
1317 			ImGui::SameLine();
1318 			ImGui::Dummy(sz);
1319 			ImGui::SameLine();
1320 			ImGui::Button("B", sz);
1321 
1322 			ImGui::TreePop();
1323 		}
1324 
1325 		if (ImGui::TreeNode("Groups"))
1326 		{
1327 			ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.)");
1328 			ImGui::BeginGroup();
1329 			{
1330 				ImGui::BeginGroup();
1331 				ImGui::Button("AAA");
1332 				ImGui::SameLine();
1333 				ImGui::Button("BBB");
1334 				ImGui::SameLine();
1335 				ImGui::BeginGroup();
1336 				ImGui::Button("CCC");
1337 				ImGui::Button("DDD");
1338 				ImGui::EndGroup();
1339 				ImGui::SameLine();
1340 				ImGui::Button("EEE");
1341 				ImGui::EndGroup();
1342 				if (ImGui::IsItemHovered())
1343 					ImGui::SetTooltip("First group hovered");
1344 			}
1345 			// Capture the group size and create widgets using the same size
1346 			ImVec2 size = ImGui::GetItemRectSize();
1347 			const float values[5] = {0.5f, 0.20f, 0.80f, 0.60f, 0.25f};
1348 			ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
1349 
1350 			ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
1351 			ImGui::SameLine();
1352 			ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
1353 			ImGui::EndGroup();
1354 			ImGui::SameLine();
1355 
1356 			ImGui::Button("LEVERAGE\nBUZZWORD", size);
1357 			ImGui::SameLine();
1358 
1359 			ImGui::ListBoxHeader("List", size);
1360 			ImGui::Selectable("Selected", true);
1361 			ImGui::Selectable("Not Selected", false);
1362 			ImGui::ListBoxFooter();
1363 
1364 			ImGui::TreePop();
1365 		}
1366 
1367 		if (ImGui::TreeNode("Text Baseline Alignment"))
1368 		{
1369 			ImGui::TextWrapped("(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)");
1370 
1371 			ImGui::Text("One\nTwo\nThree");
1372 			ImGui::SameLine();
1373 			ImGui::Text("Hello\nWorld");
1374 			ImGui::SameLine();
1375 			ImGui::Text("Banana");
1376 
1377 			ImGui::Text("Banana");
1378 			ImGui::SameLine();
1379 			ImGui::Text("Hello\nWorld");
1380 			ImGui::SameLine();
1381 			ImGui::Text("One\nTwo\nThree");
1382 
1383 			ImGui::Button("HOP##1");
1384 			ImGui::SameLine();
1385 			ImGui::Text("Banana");
1386 			ImGui::SameLine();
1387 			ImGui::Text("Hello\nWorld");
1388 			ImGui::SameLine();
1389 			ImGui::Text("Banana");
1390 
1391 			ImGui::Button("HOP##2");
1392 			ImGui::SameLine();
1393 			ImGui::Text("Hello\nWorld");
1394 			ImGui::SameLine();
1395 			ImGui::Text("Banana");
1396 
1397 			ImGui::Button("TEST##1");
1398 			ImGui::SameLine();
1399 			ImGui::Text("TEST");
1400 			ImGui::SameLine();
1401 			ImGui::SmallButton("TEST##2");
1402 
1403 			ImGui::AlignTextToFramePadding();  // If your line starts with text, call this to align it to upcoming widgets.
1404 			ImGui::Text("Text aligned to Widget");
1405 			ImGui::SameLine();
1406 			ImGui::Button("Widget##1");
1407 			ImGui::SameLine();
1408 			ImGui::Text("Widget");
1409 			ImGui::SameLine();
1410 			ImGui::SmallButton("Widget##2");
1411 			ImGui::SameLine();
1412 			ImGui::Button("Widget##3");
1413 
1414 			// Tree
1415 			const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
1416 			ImGui::Button("Button##1");
1417 			ImGui::SameLine(0.0f, spacing);
1418 			if (ImGui::TreeNode("Node##1"))
1419 			{
1420 				for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i);
1421 				ImGui::TreePop();
1422 			}  // Dummy tree data
1423 
1424 			ImGui::AlignTextToFramePadding();             // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit).
1425 			bool node_open = ImGui::TreeNode("Node##2");  // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content.
1426 			ImGui::SameLine(0.0f, spacing);
1427 			ImGui::Button("Button##2");
1428 			if (node_open)
1429 			{
1430 				for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i);
1431 				ImGui::TreePop();
1432 			}  // Dummy tree data
1433 
1434 			// Bullet
1435 			ImGui::Button("Button##3");
1436 			ImGui::SameLine(0.0f, spacing);
1437 			ImGui::BulletText("Bullet text");
1438 
1439 			ImGui::AlignTextToFramePadding();
1440 			ImGui::BulletText("Node");
1441 			ImGui::SameLine(0.0f, spacing);
1442 			ImGui::Button("Button##4");
1443 
1444 			ImGui::TreePop();
1445 		}
1446 
1447 		if (ImGui::TreeNode("Scrolling"))
1448 		{
1449 			ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)");
1450 			static bool track = true;
1451 			static int track_line = 50, scroll_to_px = 200;
1452 			ImGui::Checkbox("Track", &track);
1453 			ImGui::PushItemWidth(100);
1454 			ImGui::SameLine(130);
1455 			track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %.0f");
1456 			bool scroll_to = ImGui::Button("Scroll To Pos");
1457 			ImGui::SameLine(130);
1458 			scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "Y = %.0f px");
1459 			ImGui::PopItemWidth();
1460 			if (scroll_to) track = false;
1461 
1462 			for (int i = 0; i < 5; i++)
1463 			{
1464 				if (i > 0) ImGui::SameLine();
1465 				ImGui::BeginGroup();
1466 				ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
1467 				ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
1468 				if (scroll_to)
1469 					ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
1470 				for (int line = 0; line < 100; line++)
1471 				{
1472 					if (track && line == track_line)
1473 					{
1474 						ImGui::TextColored(ImColor(255, 255, 0), "Line %d", line);
1475 						ImGui::SetScrollHere(i * 0.25f);  // 0.0f:top, 0.5f:center, 1.0f:bottom
1476 					}
1477 					else
1478 					{
1479 						ImGui::Text("Line %d", line);
1480 					}
1481 				}
1482 				float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY();
1483 				ImGui::EndChild();
1484 				ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y);
1485 				ImGui::EndGroup();
1486 			}
1487 			ImGui::TreePop();
1488 		}
1489 
1490 		if (ImGui::TreeNode("Horizontal Scrolling"))
1491 		{
1492 			ImGui::Bullet();
1493 			ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.");
1494 			ImGui::Bullet();
1495 			ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
1496 			static int lines = 7;
1497 			ImGui::SliderInt("Lines", &lines, 1, 15);
1498 			ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
1499 			ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
1500 			ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
1501 			for (int line = 0; line < lines; line++)
1502 			{
1503 				// Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off
1504 				// manipulating the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use the lower-level ImDrawList API)
1505 				int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
1506 				for (int n = 0; n < num_buttons; n++)
1507 				{
1508 					if (n > 0) ImGui::SameLine();
1509 					ImGui::PushID(n + line * 1000);
1510 					char num_buf[16];
1511 					sprintf(num_buf, "%d", n);
1512 					const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
1513 					float hue = n * 0.05f;
1514 					ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
1515 					ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
1516 					ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
1517 					ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
1518 					ImGui::PopStyleColor(3);
1519 					ImGui::PopID();
1520 				}
1521 			}
1522 			float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX();
1523 			ImGui::EndChild();
1524 			ImGui::PopStyleVar(2);
1525 			float scroll_x_delta = 0.0f;
1526 			ImGui::SmallButton("<<");
1527 			if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f;
1528 			ImGui::SameLine();
1529 			ImGui::Text("Scroll from code");
1530 			ImGui::SameLine();
1531 			ImGui::SmallButton(">>");
1532 			if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f;
1533 			ImGui::SameLine();
1534 			ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
1535 			if (scroll_x_delta != 0.0f)
1536 			{
1537 				ImGui::BeginChild("scrolling");  // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window)
1538 				ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
1539 				ImGui::End();
1540 			}
1541 			ImGui::TreePop();
1542 		}
1543 
1544 		if (ImGui::TreeNode("Clipping"))
1545 		{
1546 			static ImVec2 size(100, 100), offset(50, 20);
1547 			ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost.");
1548 			ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f");
1549 			ImGui::TextWrapped("(Click and drag)");
1550 			ImVec2 pos = ImGui::GetCursorScreenPos();
1551 			ImVec4 clip_rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y);
1552 			ImGui::InvisibleButton("##dummy", size);
1553 			if (ImGui::IsItemActive() && ImGui::IsMouseDragging())
1554 			{
1555 				offset.x += ImGui::GetIO().MouseDelta.x;
1556 				offset.y += ImGui::GetIO().MouseDelta.y;
1557 			}
1558 			ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(90, 90, 120, 255));
1559 			ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize() * 2.0f, ImVec2(pos.x + offset.x, pos.y + offset.y), IM_COL32(255, 255, 255, 255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
1560 			ImGui::TreePop();
1561 		}
1562 	}
1563 
1564 	if (ImGui::CollapsingHeader("Popups & Modal windows"))
1565 	{
1566 		if (ImGui::TreeNode("Popups"))
1567 		{
1568 			ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
1569 
1570 			static int selected_fish = -1;
1571 			const char* names[] = {"Bream", "Haddock", "Mackerel", "Pollock", "Tilefish"};
1572 			static bool toggles[] = {true, false, false, false, false};
1573 
1574 			// Simple selection popup
1575 			// (If you want to show the current selection inside the Button itself, you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
1576 			if (ImGui::Button("Select.."))
1577 				ImGui::OpenPopup("select");
1578 			ImGui::SameLine();
1579 			ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
1580 			if (ImGui::BeginPopup("select"))
1581 			{
1582 				ImGui::Text("Aquarium");
1583 				ImGui::Separator();
1584 				for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1585 					if (ImGui::Selectable(names[i]))
1586 						selected_fish = i;
1587 				ImGui::EndPopup();
1588 			}
1589 
1590 			// Showing a menu with toggles
1591 			if (ImGui::Button("Toggle.."))
1592 				ImGui::OpenPopup("toggle");
1593 			if (ImGui::BeginPopup("toggle"))
1594 			{
1595 				for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1596 					ImGui::MenuItem(names[i], "", &toggles[i]);
1597 				if (ImGui::BeginMenu("Sub-menu"))
1598 				{
1599 					ImGui::MenuItem("Click me");
1600 					ImGui::EndMenu();
1601 				}
1602 
1603 				ImGui::Separator();
1604 				ImGui::Text("Tooltip here");
1605 				if (ImGui::IsItemHovered())
1606 					ImGui::SetTooltip("I am a tooltip over a popup");
1607 
1608 				if (ImGui::Button("Stacked Popup"))
1609 					ImGui::OpenPopup("another popup");
1610 				if (ImGui::BeginPopup("another popup"))
1611 				{
1612 					for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1613 						ImGui::MenuItem(names[i], "", &toggles[i]);
1614 					if (ImGui::BeginMenu("Sub-menu"))
1615 					{
1616 						ImGui::MenuItem("Click me");
1617 						ImGui::EndMenu();
1618 					}
1619 					ImGui::EndPopup();
1620 				}
1621 				ImGui::EndPopup();
1622 			}
1623 
1624 			if (ImGui::Button("Popup Menu.."))
1625 				ImGui::OpenPopup("FilePopup");
1626 			if (ImGui::BeginPopup("FilePopup"))
1627 			{
1628 				ShowExampleMenuFile();
1629 				ImGui::EndPopup();
1630 			}
1631 
1632 			ImGui::TreePop();
1633 		}
1634 
1635 		if (ImGui::TreeNode("Context menus"))
1636 		{
1637 			// BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
1638 			//    if (IsItemHovered() && IsMouseClicked(0))
1639 			//       OpenPopup(id);
1640 			//    return BeginPopup(id);
1641 			// For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation.
1642 			static float value = 0.5f;
1643 			ImGui::Text("Value = %.3f (<-- right-click here)", value);
1644 			if (ImGui::BeginPopupContextItem("item context menu"))
1645 			{
1646 				if (ImGui::Selectable("Set to zero")) value = 0.0f;
1647 				if (ImGui::Selectable("Set to PI")) value = 3.1415f;
1648 				ImGui::PushItemWidth(-1);
1649 				ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
1650 				ImGui::PopItemWidth();
1651 				ImGui::EndPopup();
1652 			}
1653 
1654 			static char name[32] = "Label1";
1655 			char buf[64];
1656 			sprintf(buf, "Button: %s###Button", name);  // ### operator override ID ignoring the preceding label
1657 			ImGui::Button(buf);
1658 			if (ImGui::BeginPopupContextItem())  // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
1659 			{
1660 				ImGui::Text("Edit name:");
1661 				ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
1662 				if (ImGui::Button("Close"))
1663 					ImGui::CloseCurrentPopup();
1664 				ImGui::EndPopup();
1665 			}
1666 			ImGui::SameLine();
1667 			ImGui::Text("(<-- right-click here)");
1668 
1669 			ImGui::TreePop();
1670 		}
1671 
1672 		if (ImGui::TreeNode("Modals"))
1673 		{
1674 			ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
1675 
1676 			if (ImGui::Button("Delete.."))
1677 				ImGui::OpenPopup("Delete?");
1678 			if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
1679 			{
1680 				ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
1681 				ImGui::Separator();
1682 
1683 				//static int dummy_i = 0;
1684 				//ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
1685 
1686 				static bool dont_ask_me_next_time = false;
1687 				ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
1688 				ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
1689 				ImGui::PopStyleVar();
1690 
1691 				if (ImGui::Button("OK", ImVec2(120, 0)))
1692 				{
1693 					ImGui::CloseCurrentPopup();
1694 				}
1695 				ImGui::SetItemDefaultFocus();
1696 				ImGui::SameLine();
1697 				if (ImGui::Button("Cancel", ImVec2(120, 0)))
1698 				{
1699 					ImGui::CloseCurrentPopup();
1700 				}
1701 				ImGui::EndPopup();
1702 			}
1703 
1704 			if (ImGui::Button("Stacked modals.."))
1705 				ImGui::OpenPopup("Stacked 1");
1706 			if (ImGui::BeginPopupModal("Stacked 1"))
1707 			{
1708 				ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDarkening] for darkening.");
1709 				static int item = 1;
1710 				ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
1711 				static float color[4] = {0.4f, 0.7f, 0.0f, 0.5f};
1712 				ImGui::ColorEdit4("color", color);  // This is to test behavior of stacked regular popups over a modal
1713 
1714 				if (ImGui::Button("Add another modal.."))
1715 					ImGui::OpenPopup("Stacked 2");
1716 				if (ImGui::BeginPopupModal("Stacked 2"))
1717 				{
1718 					ImGui::Text("Hello from Stacked The Second!");
1719 					if (ImGui::Button("Close"))
1720 						ImGui::CloseCurrentPopup();
1721 					ImGui::EndPopup();
1722 				}
1723 
1724 				if (ImGui::Button("Close"))
1725 					ImGui::CloseCurrentPopup();
1726 				ImGui::EndPopup();
1727 			}
1728 
1729 			ImGui::TreePop();
1730 		}
1731 
1732 		if (ImGui::TreeNode("Menus inside a regular window"))
1733 		{
1734 			ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
1735 			ImGui::Separator();
1736 			// NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above.
1737 			// To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here
1738 			// would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus.
1739 			ImGui::PushID("foo");
1740 			ImGui::MenuItem("Menu item", "CTRL+M");
1741 			if (ImGui::BeginMenu("Menu inside a regular window"))
1742 			{
1743 				ShowExampleMenuFile();
1744 				ImGui::EndMenu();
1745 			}
1746 			ImGui::PopID();
1747 			ImGui::Separator();
1748 			ImGui::TreePop();
1749 		}
1750 	}
1751 
1752 	if (ImGui::CollapsingHeader("Columns"))
1753 	{
1754 		ImGui::PushID("Columns");
1755 
1756 		// Basic columns
1757 		if (ImGui::TreeNode("Basic"))
1758 		{
1759 			ImGui::Text("Without border:");
1760 			ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
1761 			ImGui::Separator();
1762 			for (int n = 0; n < 14; n++)
1763 			{
1764 				char label[32];
1765 				sprintf(label, "Item %d", n);
1766 				if (ImGui::Selectable(label))
1767 				{
1768 				}
1769 				//if (ImGui::Button(label, ImVec2(-1,0))) {}
1770 				ImGui::NextColumn();
1771 			}
1772 			ImGui::Columns(1);
1773 			ImGui::Separator();
1774 
1775 			ImGui::Text("With border:");
1776 			ImGui::Columns(4, "mycolumns");  // 4-ways, with border
1777 			ImGui::Separator();
1778 			ImGui::Text("ID");
1779 			ImGui::NextColumn();
1780 			ImGui::Text("Name");
1781 			ImGui::NextColumn();
1782 			ImGui::Text("Path");
1783 			ImGui::NextColumn();
1784 			ImGui::Text("Hovered");
1785 			ImGui::NextColumn();
1786 			ImGui::Separator();
1787 			const char* names[3] = {"One", "Two", "Three"};
1788 			const char* paths[3] = {"/path/one", "/path/two", "/path/three"};
1789 			static int selected = -1;
1790 			for (int i = 0; i < 3; i++)
1791 			{
1792 				char label[32];
1793 				sprintf(label, "%04d", i);
1794 				if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
1795 					selected = i;
1796 				bool hovered = ImGui::IsItemHovered();
1797 				ImGui::NextColumn();
1798 				ImGui::Text(names[i]);
1799 				ImGui::NextColumn();
1800 				ImGui::Text(paths[i]);
1801 				ImGui::NextColumn();
1802 				ImGui::Text("%d", hovered);
1803 				ImGui::NextColumn();
1804 			}
1805 			ImGui::Columns(1);
1806 			ImGui::Separator();
1807 			ImGui::TreePop();
1808 		}
1809 
1810 		// Create multiple items in a same cell before switching to next column
1811 		if (ImGui::TreeNode("Mixed items"))
1812 		{
1813 			ImGui::Columns(3, "mixed");
1814 			ImGui::Separator();
1815 
1816 			ImGui::Text("Hello");
1817 			ImGui::Button("Banana");
1818 			ImGui::NextColumn();
1819 
1820 			ImGui::Text("ImGui");
1821 			ImGui::Button("Apple");
1822 			static float foo = 1.0f;
1823 			ImGui::InputFloat("red", &foo, 0.05f, 0, 3);
1824 			ImGui::Text("An extra line here.");
1825 			ImGui::NextColumn();
1826 
1827 			ImGui::Text("Sailor");
1828 			ImGui::Button("Corniflower");
1829 			static float bar = 1.0f;
1830 			ImGui::InputFloat("blue", &bar, 0.05f, 0, 3);
1831 			ImGui::NextColumn();
1832 
1833 			if (ImGui::CollapsingHeader("Category A"))
1834 			{
1835 				ImGui::Text("Blah blah blah");
1836 			}
1837 			ImGui::NextColumn();
1838 			if (ImGui::CollapsingHeader("Category B"))
1839 			{
1840 				ImGui::Text("Blah blah blah");
1841 			}
1842 			ImGui::NextColumn();
1843 			if (ImGui::CollapsingHeader("Category C"))
1844 			{
1845 				ImGui::Text("Blah blah blah");
1846 			}
1847 			ImGui::NextColumn();
1848 			ImGui::Columns(1);
1849 			ImGui::Separator();
1850 			ImGui::TreePop();
1851 		}
1852 
1853 		// Word wrapping
1854 		if (ImGui::TreeNode("Word-wrapping"))
1855 		{
1856 			ImGui::Columns(2, "word-wrapping");
1857 			ImGui::Separator();
1858 			ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
1859 			ImGui::TextWrapped("Hello Left");
1860 			ImGui::NextColumn();
1861 			ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
1862 			ImGui::TextWrapped("Hello Right");
1863 			ImGui::Columns(1);
1864 			ImGui::Separator();
1865 			ImGui::TreePop();
1866 		}
1867 
1868 		if (ImGui::TreeNode("Borders"))
1869 		{
1870 			// NB: Future columns API should allow automatic horizontal borders.
1871 			static bool h_borders = true;
1872 			static bool v_borders = true;
1873 			ImGui::Checkbox("horizontal", &h_borders);
1874 			ImGui::SameLine();
1875 			ImGui::Checkbox("vertical", &v_borders);
1876 			ImGui::Columns(4, NULL, v_borders);
1877 			for (int i = 0; i < 4 * 3; i++)
1878 			{
1879 				if (h_borders && ImGui::GetColumnIndex() == 0)
1880 					ImGui::Separator();
1881 				ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i);
1882 				ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());
1883 				ImGui::NextColumn();
1884 			}
1885 			ImGui::Columns(1);
1886 			if (h_borders)
1887 				ImGui::Separator();
1888 			ImGui::TreePop();
1889 		}
1890 
1891 		// Scrolling columns
1892 		/*
1893         if (ImGui::TreeNode("Vertical Scrolling"))
1894         {
1895             ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
1896             ImGui::Columns(3);
1897             ImGui::Text("ID"); ImGui::NextColumn();
1898             ImGui::Text("Name"); ImGui::NextColumn();
1899             ImGui::Text("Path"); ImGui::NextColumn();
1900             ImGui::Columns(1);
1901             ImGui::Separator();
1902             ImGui::EndChild();
1903             ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
1904             ImGui::Columns(3);
1905             for (int i = 0; i < 10; i++)
1906             {
1907                 ImGui::Text("%04d", i); ImGui::NextColumn();
1908                 ImGui::Text("Foobar"); ImGui::NextColumn();
1909                 ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
1910             }
1911             ImGui::Columns(1);
1912             ImGui::EndChild();
1913             ImGui::TreePop();
1914         }
1915         */
1916 
1917 		if (ImGui::TreeNode("Horizontal Scrolling"))
1918 		{
1919 			ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
1920 			ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar);
1921 			ImGui::Columns(10);
1922 			int ITEMS_COUNT = 2000;
1923 			ImGuiListClipper clipper(ITEMS_COUNT);  // Also demonstrate using the clipper for large list
1924 			while (clipper.Step())
1925 			{
1926 				for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
1927 					for (int j = 0; j < 10; j++)
1928 					{
1929 						ImGui::Text("Line %d Column %d...", i, j);
1930 						ImGui::NextColumn();
1931 					}
1932 			}
1933 			ImGui::Columns(1);
1934 			ImGui::EndChild();
1935 			ImGui::TreePop();
1936 		}
1937 
1938 		bool node_open = ImGui::TreeNode("Tree within single cell");
1939 		ImGui::SameLine();
1940 		ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
1941 		if (node_open)
1942 		{
1943 			ImGui::Columns(2, "tree items");
1944 			ImGui::Separator();
1945 			if (ImGui::TreeNode("Hello"))
1946 			{
1947 				ImGui::BulletText("Sailor");
1948 				ImGui::TreePop();
1949 			}
1950 			ImGui::NextColumn();
1951 			if (ImGui::TreeNode("Bonjour"))
1952 			{
1953 				ImGui::BulletText("Marin");
1954 				ImGui::TreePop();
1955 			}
1956 			ImGui::NextColumn();
1957 			ImGui::Columns(1);
1958 			ImGui::Separator();
1959 			ImGui::TreePop();
1960 		}
1961 		ImGui::PopID();
1962 	}
1963 
1964 	if (ImGui::CollapsingHeader("Filtering"))
1965 	{
1966 		static ImGuiTextFilter filter;
1967 		ImGui::Text(
1968 			"Filter usage:\n"
1969 			"  \"\"         display all lines\n"
1970 			"  \"xxx\"      display lines containing \"xxx\"\n"
1971 			"  \"xxx,yyy\"  display lines containing \"xxx\" or \"yyy\"\n"
1972 			"  \"-xxx\"     hide lines containing \"xxx\"");
1973 		filter.Draw();
1974 		const char* lines[] = {"aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world"};
1975 		for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
1976 			if (filter.PassFilter(lines[i]))
1977 				ImGui::BulletText("%s", lines[i]);
1978 	}
1979 
1980 	if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
1981 	{
1982 		ImGuiIO& io = ImGui::GetIO();
1983 
1984 		ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
1985 		ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
1986 		ImGui::Text("WantTextInput: %d", io.WantTextInput);
1987 		ImGui::Text("WantMoveMouse: %d", io.WantMoveMouse);
1988 		ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
1989 
1990 		ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
1991 		ImGui::SameLine();
1992 		ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
1993 		ImGui::CheckboxFlags("io.NavFlags: EnableGamepad", (unsigned int*)&io.NavFlags, ImGuiNavFlags_EnableGamepad);
1994 		ImGui::CheckboxFlags("io.NavFlags: EnableKeyboard", (unsigned int*)&io.NavFlags, ImGuiNavFlags_EnableKeyboard);
1995 		ImGui::CheckboxFlags("io.NavFlags: MoveMouse", (unsigned int*)&io.NavFlags, ImGuiNavFlags_MoveMouse);
1996 		ImGui::SameLine();
1997 		ShowHelpMarker("Request ImGui to move your move cursor when using gamepad/keyboard navigation. NewFrame() will change io.MousePos and set the io.WantMoveMouse flag, your backend will need to apply the new mouse position.");
1998 
1999 		if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
2000 		{
2001 			if (ImGui::IsMousePosValid())
2002 				ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
2003 			else
2004 				ImGui::Text("Mouse pos: <INVALID>");
2005 			ImGui::Text("Mouse down:");
2006 			for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
2007 				if (io.MouseDownDuration[i] >= 0.0f)
2008 				{
2009 					ImGui::SameLine();
2010 					ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]);
2011 				}
2012 			ImGui::Text("Mouse clicked:");
2013 			for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
2014 				if (ImGui::IsMouseClicked(i))
2015 				{
2016 					ImGui::SameLine();
2017 					ImGui::Text("b%d", i);
2018 				}
2019 			ImGui::Text("Mouse dbl-clicked:");
2020 			for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
2021 				if (ImGui::IsMouseDoubleClicked(i))
2022 				{
2023 					ImGui::SameLine();
2024 					ImGui::Text("b%d", i);
2025 				}
2026 			ImGui::Text("Mouse released:");
2027 			for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
2028 				if (ImGui::IsMouseReleased(i))
2029 				{
2030 					ImGui::SameLine();
2031 					ImGui::Text("b%d", i);
2032 				}
2033 			ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
2034 
2035 			ImGui::Text("Keys down:");
2036 			for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++)
2037 				if (io.KeysDownDuration[i] >= 0.0f)
2038 				{
2039 					ImGui::SameLine();
2040 					ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]);
2041 				}
2042 			ImGui::Text("Keys pressed:");
2043 			for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++)
2044 				if (ImGui::IsKeyPressed(i))
2045 				{
2046 					ImGui::SameLine();
2047 					ImGui::Text("%d", i);
2048 				}
2049 			ImGui::Text("Keys release:");
2050 			for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++)
2051 				if (ImGui::IsKeyReleased(i))
2052 				{
2053 					ImGui::SameLine();
2054 					ImGui::Text("%d", i);
2055 				}
2056 			ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
2057 
2058 			ImGui::Text("NavInputs down:");
2059 			for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++)
2060 				if (io.NavInputs[i] > 0.0f)
2061 				{
2062 					ImGui::SameLine();
2063 					ImGui::Text("[%d] %.2f", i, io.NavInputs[i]);
2064 				}
2065 			ImGui::Text("NavInputs pressed:");
2066 			for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++)
2067 				if (io.NavInputsDownDuration[i] == 0.0f)
2068 				{
2069 					ImGui::SameLine();
2070 					ImGui::Text("[%d]", i);
2071 				}
2072 			ImGui::Text("NavInputs duration:");
2073 			for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++)
2074 				if (io.NavInputsDownDuration[i] >= 0.0f)
2075 				{
2076 					ImGui::SameLine();
2077 					ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]);
2078 				}
2079 
2080 			ImGui::Button("Hovering me sets the\nkeyboard capture flag");
2081 			if (ImGui::IsItemHovered())
2082 				ImGui::CaptureKeyboardFromApp(true);
2083 			ImGui::SameLine();
2084 			ImGui::Button("Holding me clears the\nthe keyboard capture flag");
2085 			if (ImGui::IsItemActive())
2086 				ImGui::CaptureKeyboardFromApp(false);
2087 
2088 			ImGui::TreePop();
2089 		}
2090 
2091 		if (ImGui::TreeNode("Tabbing"))
2092 		{
2093 			ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
2094 			static char buf[32] = "dummy";
2095 			ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
2096 			ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
2097 			ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
2098 			ImGui::PushAllowKeyboardFocus(false);
2099 			ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
2100 			//ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
2101 			ImGui::PopAllowKeyboardFocus();
2102 			ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
2103 			ImGui::TreePop();
2104 		}
2105 
2106 		if (ImGui::TreeNode("Focus from code"))
2107 		{
2108 			bool focus_1 = ImGui::Button("Focus on 1");
2109 			ImGui::SameLine();
2110 			bool focus_2 = ImGui::Button("Focus on 2");
2111 			ImGui::SameLine();
2112 			bool focus_3 = ImGui::Button("Focus on 3");
2113 			int has_focus = 0;
2114 			static char buf[128] = "click on a button to set focus";
2115 
2116 			if (focus_1) ImGui::SetKeyboardFocusHere();
2117 			ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
2118 			if (ImGui::IsItemActive()) has_focus = 1;
2119 
2120 			if (focus_2) ImGui::SetKeyboardFocusHere();
2121 			ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
2122 			if (ImGui::IsItemActive()) has_focus = 2;
2123 
2124 			ImGui::PushAllowKeyboardFocus(false);
2125 			if (focus_3) ImGui::SetKeyboardFocusHere();
2126 			ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
2127 			if (ImGui::IsItemActive()) has_focus = 3;
2128 			ImGui::PopAllowKeyboardFocus();
2129 
2130 			if (has_focus)
2131 				ImGui::Text("Item with focus: %d", has_focus);
2132 			else
2133 				ImGui::Text("Item with focus: <none>");
2134 
2135 			// Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
2136 			static float f3[3] = {0.0f, 0.0f, 0.0f};
2137 			int focus_ahead = -1;
2138 			if (ImGui::Button("Focus on X")) focus_ahead = 0;
2139 			ImGui::SameLine();
2140 			if (ImGui::Button("Focus on Y")) focus_ahead = 1;
2141 			ImGui::SameLine();
2142 			if (ImGui::Button("Focus on Z")) focus_ahead = 2;
2143 			if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
2144 			ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
2145 
2146 			ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
2147 			ImGui::TreePop();
2148 		}
2149 
2150 		if (ImGui::TreeNode("Focused & Hovered Test"))
2151 		{
2152 			static bool embed_all_inside_a_child_window = false;
2153 			ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
2154 			if (embed_all_inside_a_child_window)
2155 				ImGui::BeginChild("embeddingchild", ImVec2(0, ImGui::GetFontSize() * 25), true);
2156 
2157 			// Testing IsWindowFocused() function with its various flags (note that the flags can be combined)
2158 			ImGui::BulletText(
2159 				"IsWindowFocused() = %d\n"
2160 				"IsWindowFocused(_ChildWindows) = %d\n"
2161 				"IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
2162 				"IsWindowFocused(_RootWindow) = %d\n"
2163 				"IsWindowFocused(_AnyWindow) = %d\n",
2164 				ImGui::IsWindowFocused(),
2165 				ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
2166 				ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
2167 				ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
2168 				ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
2169 
2170 			// Testing IsWindowHovered() function with its various flags (note that the flags can be combined)
2171 			ImGui::BulletText(
2172 				"IsWindowHovered() = %d\n"
2173 				"IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
2174 				"IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
2175 				"IsWindowHovered(_ChildWindows) = %d\n"
2176 				"IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
2177 				"IsWindowHovered(_RootWindow) = %d\n"
2178 				"IsWindowHovered(_AnyWindow) = %d\n",
2179 				ImGui::IsWindowHovered(),
2180 				ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
2181 				ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
2182 				ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
2183 				ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
2184 				ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
2185 				ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
2186 
2187 			// Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code)
2188 			ImGui::Button("ITEM");
2189 			ImGui::BulletText(
2190 				"IsItemHovered() = %d\n"
2191 				"IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
2192 				"IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
2193 				"IsItemHovered(_AllowWhenOverlapped) = %d\n"
2194 				"IsItemhovered(_RectOnly) = %d\n",
2195 				ImGui::IsItemHovered(),
2196 				ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
2197 				ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
2198 				ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
2199 				ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly));
2200 
2201 			ImGui::BeginChild("child", ImVec2(0, 50), true);
2202 			ImGui::Text("This is another child window for testing IsWindowHovered() flags.");
2203 			ImGui::EndChild();
2204 
2205 			if (embed_all_inside_a_child_window)
2206 				EndChild();
2207 
2208 			ImGui::TreePop();
2209 		}
2210 
2211 		if (ImGui::TreeNode("Dragging"))
2212 		{
2213 			ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
2214 			for (int button = 0; button < 3; button++)
2215 				ImGui::Text("IsMouseDragging(%d):\n  w/ default threshold: %d,\n  w/ zero threshold: %d\n  w/ large threshold: %d",
2216 							button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f));
2217 			ImGui::Button("Drag Me");
2218 			if (ImGui::IsItemActive())
2219 			{
2220 				// Draw a line between the button and the mouse cursor
2221 				ImDrawList* draw_list = ImGui::GetWindowDrawList();
2222 				draw_list->PushClipRectFullScreen();
2223 				draw_list->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f);
2224 				draw_list->PopClipRect();
2225 
2226 				// Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold)
2227 				// You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta()
2228 				ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
2229 				ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
2230 				ImVec2 mouse_delta = io.MouseDelta;
2231 				ImGui::SameLine();
2232 				ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y);
2233 			}
2234 			ImGui::TreePop();
2235 		}
2236 
2237 		if (ImGui::TreeNode("Mouse cursors"))
2238 		{
2239 			const char* mouse_cursors_names[] = {"Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE"};
2240 			IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_Count_);
2241 
2242 			ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]);
2243 			ImGui::Text("Hover to see mouse cursors:");
2244 			ImGui::SameLine();
2245 			ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it.");
2246 			for (int i = 0; i < ImGuiMouseCursor_Count_; i++)
2247 			{
2248 				char label[32];
2249 				sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
2250 				ImGui::Bullet();
2251 				ImGui::Selectable(label, false);
2252 				if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
2253 					ImGui::SetMouseCursor(i);
2254 			}
2255 			ImGui::TreePop();
2256 		}
2257 	}
2258 
2259 	ImGui::End();
2260 }
2261 
2262 // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
2263 // Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally.
ShowStyleSelector(const char * label)2264 bool ImGui::ShowStyleSelector(const char* label)
2265 {
2266 	static int style_idx = -1;
2267 	if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
2268 	{
2269 		switch (style_idx)
2270 		{
2271 			case 0:
2272 				ImGui::StyleColorsClassic();
2273 				break;
2274 			case 1:
2275 				ImGui::StyleColorsDark();
2276 				break;
2277 			case 2:
2278 				ImGui::StyleColorsLight();
2279 				break;
2280 		}
2281 		return true;
2282 	}
2283 	return false;
2284 }
2285 
2286 // Demo helper function to select among loaded fonts.
2287 // Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
ShowFontSelector(const char * label)2288 void ImGui::ShowFontSelector(const char* label)
2289 {
2290 	ImGuiIO& io = ImGui::GetIO();
2291 	ImFont* font_current = ImGui::GetFont();
2292 	if (ImGui::BeginCombo(label, font_current->GetDebugName()))
2293 	{
2294 		for (int n = 0; n < io.Fonts->Fonts.Size; n++)
2295 			if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current))
2296 				io.FontDefault = io.Fonts->Fonts[n];
2297 		ImGui::EndCombo();
2298 	}
2299 	ImGui::SameLine();
2300 	ShowHelpMarker(
2301 		"- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
2302 		"- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
2303 		"- Read FAQ and documentation in misc/fonts/ for more details.\n"
2304 		"- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
2305 }
2306 
ShowStyleEditor(ImGuiStyle * ref)2307 void ImGui::ShowStyleEditor(ImGuiStyle* ref)
2308 {
2309 	// You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference)
2310 	ImGuiStyle& style = ImGui::GetStyle();
2311 	static ImGuiStyle ref_saved_style;
2312 
2313 	// Default to using internal storage as reference
2314 	static bool init = true;
2315 	if (init && ref == NULL)
2316 		ref_saved_style = style;
2317 	init = false;
2318 	if (ref == NULL)
2319 		ref = &ref_saved_style;
2320 
2321 	ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
2322 
2323 	if (ImGui::ShowStyleSelector("Colors##Selector"))
2324 		ref_saved_style = style;
2325 	ImGui::ShowFontSelector("Fonts##Selector");
2326 
2327 	// Simplified Settings
2328 	if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
2329 		style.GrabRounding = style.FrameRounding;  // Make GrabRounding always the same value as FrameRounding
2330 	{
2331 		bool window_border = (style.WindowBorderSize > 0.0f);
2332 		if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f;
2333 	}
2334 	ImGui::SameLine();
2335 	{
2336 		bool frame_border = (style.FrameBorderSize > 0.0f);
2337 		if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f;
2338 	}
2339 	ImGui::SameLine();
2340 	{
2341 		bool popup_border = (style.PopupBorderSize > 0.0f);
2342 		if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f;
2343 	}
2344 
2345 	// Save/Revert button
2346 	if (ImGui::Button("Save Ref"))
2347 		*ref = ref_saved_style = style;
2348 	ImGui::SameLine();
2349 	if (ImGui::Button("Revert Ref"))
2350 		style = *ref;
2351 	ImGui::SameLine();
2352 	ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
2353 
2354 	if (ImGui::TreeNode("Rendering"))
2355 	{
2356 		ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
2357 		ImGui::SameLine();
2358 		ShowHelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
2359 		ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
2360 		ImGui::PushItemWidth(100);
2361 		ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f);
2362 		if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f;
2363 		ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f");  // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.
2364 		ImGui::PopItemWidth();
2365 		ImGui::TreePop();
2366 	}
2367 
2368 	if (ImGui::TreeNode("Settings"))
2369 	{
2370 		ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
2371 		ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 16.0f, "%.0f");
2372 		ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
2373 		ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
2374 		ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
2375 		ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
2376 		ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
2377 		ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
2378 		ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
2379 		ImGui::Text("BorderSize");
2380 		ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
2381 		ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
2382 		ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
2383 		ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
2384 		ImGui::Text("Rounding");
2385 		ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f");
2386 		ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f");
2387 		ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
2388 		ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
2389 		ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
2390 		ImGui::Text("Alignment");
2391 		ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
2392 		ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
2393 		ImGui::SameLine();
2394 		ShowHelpMarker("Alignment applies when a button is larger than its text content.");
2395 		ImGui::TreePop();
2396 	}
2397 
2398 	if (ImGui::TreeNode("Colors"))
2399 	{
2400 		static int output_dest = 0;
2401 		static bool output_only_modified = true;
2402 		if (ImGui::Button("Export Unsaved"))
2403 		{
2404 			if (output_dest == 0)
2405 				ImGui::LogToClipboard();
2406 			else
2407 				ImGui::LogToTTY();
2408 			ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
2409 			for (int i = 0; i < ImGuiCol_COUNT; i++)
2410 			{
2411 				const ImVec4& col = style.Colors[i];
2412 				const char* name = ImGui::GetStyleColorName(i);
2413 				if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
2414 					ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
2415 			}
2416 			ImGui::LogFinish();
2417 		}
2418 		ImGui::SameLine();
2419 		ImGui::PushItemWidth(120);
2420 		ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
2421 		ImGui::PopItemWidth();
2422 		ImGui::SameLine();
2423 		ImGui::Checkbox("Only Modified Colors", &output_only_modified);
2424 
2425 		ImGui::Text("Tip: Left-click on colored square to open color picker,\nRight-click to open edit options menu.");
2426 
2427 		static ImGuiTextFilter filter;
2428 		filter.Draw("Filter colors", 200);
2429 
2430 		static ImGuiColorEditFlags alpha_flags = 0;
2431 		ImGui::RadioButton("Opaque", &alpha_flags, 0);
2432 		ImGui::SameLine();
2433 		ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview);
2434 		ImGui::SameLine();
2435 		ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf);
2436 
2437 		ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
2438 		ImGui::PushItemWidth(-160);
2439 		for (int i = 0; i < ImGuiCol_COUNT; i++)
2440 		{
2441 			const char* name = ImGui::GetStyleColorName(i);
2442 			if (!filter.PassFilter(name))
2443 				continue;
2444 			ImGui::PushID(i);
2445 			ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
2446 			if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
2447 			{
2448 				// Tips: in a real user application, you may want to merge and use an icon font into the main font, so instead of "Save"/"Revert" you'd use icons.
2449 				// Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient!
2450 				ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
2451 				if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
2452 				ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
2453 				if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
2454 			}
2455 			ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
2456 			ImGui::TextUnformatted(name);
2457 			ImGui::PopID();
2458 		}
2459 		ImGui::PopItemWidth();
2460 		ImGui::EndChild();
2461 
2462 		ImGui::TreePop();
2463 	}
2464 
2465 	bool fonts_opened = ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size);
2466 	if (fonts_opened)
2467 	{
2468 		ImFontAtlas* atlas = ImGui::GetIO().Fonts;
2469 		if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
2470 		{
2471 			ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128));
2472 			ImGui::TreePop();
2473 		}
2474 		ImGui::PushItemWidth(100);
2475 		for (int i = 0; i < atlas->Fonts.Size; i++)
2476 		{
2477 			ImFont* font = atlas->Fonts[i];
2478 			ImGui::PushID(font);
2479 			bool font_details_opened = ImGui::TreeNode(font, "Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size);
2480 			ImGui::SameLine();
2481 			if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font;
2482 			if (font_details_opened)
2483 			{
2484 				ImGui::PushFont(font);
2485 				ImGui::Text("The quick brown fox jumps over the lazy dog");
2486 				ImGui::PopFont();
2487 				ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");  // Scale only this font
2488 				ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, 0);
2489 				ImGui::SameLine();
2490 				ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)");
2491 				ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
2492 				ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
2493 				ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface));
2494 				for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
2495 				{
2496 					ImFontConfig* cfg = &font->ConfigData[config_i];
2497 					ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
2498 				}
2499 				if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
2500 				{
2501 					// Display all glyphs of the fonts in separate pages of 256 characters
2502 					const ImFontGlyph* glyph_fallback = font->FallbackGlyph;  // Forcefully/dodgily make FindGlyph() return NULL on fallback, which isn't the default behavior.
2503 					font->FallbackGlyph = NULL;
2504 					for (int base = 0; base < 0x10000; base += 256)
2505 					{
2506 						int count = 0;
2507 						for (int n = 0; n < 256; n++)
2508 							count += font->FindGlyph((ImWchar)(base + n)) ? 1 : 0;
2509 						if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))
2510 						{
2511 							float cell_spacing = style.ItemSpacing.y;
2512 							ImVec2 cell_size(font->FontSize * 1, font->FontSize * 1);
2513 							ImVec2 base_pos = ImGui::GetCursorScreenPos();
2514 							ImDrawList* draw_list = ImGui::GetWindowDrawList();
2515 							for (int n = 0; n < 256; n++)
2516 							{
2517 								ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing));
2518 								ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y);
2519 								const ImFontGlyph* glyph = font->FindGlyph((ImWchar)(base + n));
2520 								;
2521 								draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
2522 								font->RenderChar(draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base + n));  // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string.
2523 								if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
2524 								{
2525 									ImGui::BeginTooltip();
2526 									ImGui::Text("Codepoint: U+%04X", base + n);
2527 									ImGui::Separator();
2528 									ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
2529 									ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
2530 									ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
2531 									ImGui::EndTooltip();
2532 								}
2533 							}
2534 							ImGui::Dummy(ImVec2((cell_size.x + cell_spacing) * 16, (cell_size.y + cell_spacing) * 16));
2535 							ImGui::TreePop();
2536 						}
2537 					}
2538 					font->FallbackGlyph = glyph_fallback;
2539 					ImGui::TreePop();
2540 				}
2541 				ImGui::TreePop();
2542 			}
2543 			ImGui::PopID();
2544 		}
2545 		static float window_scale = 1.0f;
2546 		ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f");               // scale only this window
2547 		ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f");  // scale everything
2548 		ImGui::PopItemWidth();
2549 		ImGui::SetWindowFontScale(window_scale);
2550 		ImGui::TreePop();
2551 	}
2552 
2553 	ImGui::PopItemWidth();
2554 }
2555 
2556 // Demonstrate creating a fullscreen menu bar and populating it.
ShowExampleAppMainMenuBar()2557 static void ShowExampleAppMainMenuBar()
2558 {
2559 	if (ImGui::BeginMainMenuBar())
2560 	{
2561 		if (ImGui::BeginMenu("File"))
2562 		{
2563 			ShowExampleMenuFile();
2564 			ImGui::EndMenu();
2565 		}
2566 		if (ImGui::BeginMenu("Edit"))
2567 		{
2568 			if (ImGui::MenuItem("Undo", "CTRL+Z"))
2569 			{
2570 			}
2571 			if (ImGui::MenuItem("Redo", "CTRL+Y", false, false))
2572 			{
2573 			}  // Disabled item
2574 			ImGui::Separator();
2575 			if (ImGui::MenuItem("Cut", "CTRL+X"))
2576 			{
2577 			}
2578 			if (ImGui::MenuItem("Copy", "CTRL+C"))
2579 			{
2580 			}
2581 			if (ImGui::MenuItem("Paste", "CTRL+V"))
2582 			{
2583 			}
2584 			ImGui::EndMenu();
2585 		}
2586 		ImGui::EndMainMenuBar();
2587 	}
2588 }
2589 
ShowExampleMenuFile()2590 static void ShowExampleMenuFile()
2591 {
2592 	ImGui::MenuItem("(dummy menu)", NULL, false, false);
2593 	if (ImGui::MenuItem("New"))
2594 	{
2595 	}
2596 	if (ImGui::MenuItem("Open", "Ctrl+O"))
2597 	{
2598 	}
2599 	if (ImGui::BeginMenu("Open Recent"))
2600 	{
2601 		ImGui::MenuItem("fish_hat.c");
2602 		ImGui::MenuItem("fish_hat.inl");
2603 		ImGui::MenuItem("fish_hat.h");
2604 		if (ImGui::BeginMenu("More.."))
2605 		{
2606 			ImGui::MenuItem("Hello");
2607 			ImGui::MenuItem("Sailor");
2608 			if (ImGui::BeginMenu("Recurse.."))
2609 			{
2610 				ShowExampleMenuFile();
2611 				ImGui::EndMenu();
2612 			}
2613 			ImGui::EndMenu();
2614 		}
2615 		ImGui::EndMenu();
2616 	}
2617 	if (ImGui::MenuItem("Save", "Ctrl+S"))
2618 	{
2619 	}
2620 	if (ImGui::MenuItem("Save As.."))
2621 	{
2622 	}
2623 	ImGui::Separator();
2624 	if (ImGui::BeginMenu("Options"))
2625 	{
2626 		static bool enabled = true;
2627 		ImGui::MenuItem("Enabled", "", &enabled);
2628 		ImGui::BeginChild("child", ImVec2(0, 60), true);
2629 		for (int i = 0; i < 10; i++)
2630 			ImGui::Text("Scrolling Text %d", i);
2631 		ImGui::EndChild();
2632 		static float f = 0.5f;
2633 		static int n = 0;
2634 		static bool b = true;
2635 		ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
2636 		ImGui::InputFloat("Input", &f, 0.1f);
2637 		ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
2638 		ImGui::Checkbox("Check", &b);
2639 		ImGui::EndMenu();
2640 	}
2641 	if (ImGui::BeginMenu("Colors"))
2642 	{
2643 		float sz = ImGui::GetTextLineHeight();
2644 		for (int i = 0; i < ImGuiCol_COUNT; i++)
2645 		{
2646 			const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
2647 			ImVec2 p = ImGui::GetCursorScreenPos();
2648 			ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i));
2649 			ImGui::Dummy(ImVec2(sz, sz));
2650 			ImGui::SameLine();
2651 			ImGui::MenuItem(name);
2652 		}
2653 		ImGui::EndMenu();
2654 	}
2655 	if (ImGui::BeginMenu("Disabled", false))  // Disabled
2656 	{
2657 		IM_ASSERT(0);
2658 	}
2659 	if (ImGui::MenuItem("Checked", NULL, true))
2660 	{
2661 	}
2662 	if (ImGui::MenuItem("Quit", "Alt+F4"))
2663 	{
2664 	}
2665 }
2666 
2667 // Demonstrate creating a window which gets auto-resized according to its content.
ShowExampleAppAutoResize(bool * p_open)2668 static void ShowExampleAppAutoResize(bool* p_open)
2669 {
2670 	if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
2671 	{
2672 		ImGui::End();
2673 		return;
2674 	}
2675 
2676 	static int lines = 10;
2677 	ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop.");
2678 	ImGui::SliderInt("Number of lines", &lines, 1, 20);
2679 	for (int i = 0; i < lines; i++)
2680 		ImGui::Text("%*sThis is line %d", i * 4, "", i);  // Pad with space to extend size horizontally
2681 	ImGui::End();
2682 }
2683 
2684 // Demonstrate creating a window with custom resize constraints.
ShowExampleAppConstrainedResize(bool * p_open)2685 static void ShowExampleAppConstrainedResize(bool* p_open)
2686 {
2687 	struct CustomConstraints  // Helper functions to demonstrate programmatic constraints
2688 	{
2689 		static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }
2690 		static void Step(ImGuiSizeCallbackData* data)
2691 		{
2692 			float step = (float)(int)(intptr_t)data->UserData;
2693 			data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step);
2694 		}
2695 	};
2696 
2697 	static bool auto_resize = false;
2698 	static int type = 0;
2699 	static int display_lines = 10;
2700 	if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX));                                           // Vertical only
2701 	if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1));                                           // Horizontal only
2702 	if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX));                                   // Width > 100, Height > 100
2703 	if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1));                                             // Width 400-500
2704 	if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500));                                             // Height 400-500
2705 	if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);            // Always Square
2706 	if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);  // Fixed Step
2707 
2708 	ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
2709 	if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
2710 	{
2711 		const char* desc[] =
2712 			{
2713 				"Resize vertical only",
2714 				"Resize horizontal only",
2715 				"Width > 100, Height > 100",
2716 				"Width 400-500",
2717 				"Height 400-500",
2718 				"Custom: Always Square",
2719 				"Custom: Fixed Steps (100)",
2720 			};
2721 		if (ImGui::Button("200x200"))
2722 		{
2723 			ImGui::SetWindowSize(ImVec2(200, 200));
2724 		}
2725 		ImGui::SameLine();
2726 		if (ImGui::Button("500x500"))
2727 		{
2728 			ImGui::SetWindowSize(ImVec2(500, 500));
2729 		}
2730 		ImGui::SameLine();
2731 		if (ImGui::Button("800x200"))
2732 		{
2733 			ImGui::SetWindowSize(ImVec2(800, 200));
2734 		}
2735 		ImGui::PushItemWidth(200);
2736 		ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
2737 		ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
2738 		ImGui::PopItemWidth();
2739 		ImGui::Checkbox("Auto-resize", &auto_resize);
2740 		for (int i = 0; i < display_lines; i++)
2741 			ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
2742 	}
2743 	ImGui::End();
2744 }
2745 
2746 // Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
ShowExampleAppFixedOverlay(bool * p_open)2747 static void ShowExampleAppFixedOverlay(bool* p_open)
2748 {
2749 	const float DISTANCE = 10.0f;
2750 	static int corner = 0;
2751 	ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE);
2752 	ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
2753 	ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
2754 	ImGui::SetNextWindowBgAlpha(0.3f);  // Transparent background
2755 	if (ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
2756 	{
2757 		ImGui::Text("Simple overlay\nin the corner of the screen.\n(right-click to change position)");
2758 		ImGui::Separator();
2759 		ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
2760 		if (ImGui::BeginPopupContextWindow())
2761 		{
2762 			if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
2763 			if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
2764 			if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
2765 			if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
2766 			if (p_open && ImGui::MenuItem("Close")) *p_open = false;
2767 			ImGui::EndPopup();
2768 		}
2769 		ImGui::End();
2770 	}
2771 }
2772 
2773 // Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
2774 // This apply to regular items as well. Read FAQ section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." for details.
ShowExampleAppWindowTitles(bool *)2775 static void ShowExampleAppWindowTitles(bool*)
2776 {
2777 	// By default, Windows are uniquely identified by their title.
2778 	// You can use the "##" and "###" markers to manipulate the display/ID.
2779 
2780 	// Using "##" to display same title but have unique identifier.
2781 	ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
2782 	ImGui::Begin("Same title as another window##1");
2783 	ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
2784 	ImGui::End();
2785 
2786 	ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
2787 	ImGui::Begin("Same title as another window##2");
2788 	ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
2789 	ImGui::End();
2790 
2791 	// Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
2792 	char buf[128];
2793 	sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
2794 	ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
2795 	ImGui::Begin(buf);
2796 	ImGui::Text("This window has a changing title.");
2797 	ImGui::End();
2798 }
2799 
2800 // Demonstrate using the low-level ImDrawList to draw custom shapes.
ShowExampleAppCustomRendering(bool * p_open)2801 static void ShowExampleAppCustomRendering(bool* p_open)
2802 {
2803 	ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiCond_FirstUseEver);
2804 	if (!ImGui::Begin("Example: Custom rendering", p_open))
2805 	{
2806 		ImGui::End();
2807 		return;
2808 	}
2809 
2810 	// Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
2811 	// Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
2812 	// ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
2813 	// In this example we are not using the maths operators!
2814 	ImDrawList* draw_list = ImGui::GetWindowDrawList();
2815 
2816 	// Primitives
2817 	ImGui::Text("Primitives");
2818 	static float sz = 36.0f;
2819 	static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
2820 	ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
2821 	ImGui::ColorEdit3("Color", &col.x);
2822 	{
2823 		const ImVec2 p = ImGui::GetCursorScreenPos();
2824 		const ImU32 col32 = ImColor(col);
2825 		float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
2826 		for (int n = 0; n < 2; n++)
2827 		{
2828 			float thickness = (n == 0) ? 1.0f : 4.0f;
2829 			draw_list->AddCircle(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col32, 20, thickness);
2830 			x += sz + spacing;
2831 			draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 0.0f, ImDrawCornerFlags_All, thickness);
2832 			x += sz + spacing;
2833 			draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f, ImDrawCornerFlags_All, thickness);
2834 			x += sz + spacing;
2835 			draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f, ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight, thickness);
2836 			x += sz + spacing;
2837 			draw_list->AddTriangle(ImVec2(x + sz * 0.5f, y), ImVec2(x + sz, y + sz - 0.5f), ImVec2(x, y + sz - 0.5f), col32, thickness);
2838 			x += sz + spacing;
2839 			draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col32, thickness);
2840 			x += sz + spacing;
2841 			draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, thickness);
2842 			x += sz + spacing;
2843 			draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col32, thickness);
2844 			x += spacing;
2845 			draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x + sz * 1.3f, y + sz * 0.3f), ImVec2(x + sz - sz * 1.3f, y + sz - sz * 0.3f), ImVec2(x + sz, y + sz), col32, thickness);
2846 			x = p.x + 4;
2847 			y += sz + spacing;
2848 		}
2849 		draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col32, 32);
2850 		x += sz + spacing;
2851 		draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col32);
2852 		x += sz + spacing;
2853 		draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f);
2854 		x += sz + spacing;
2855 		draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f, ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight);
2856 		x += sz + spacing;
2857 		draw_list->AddTriangleFilled(ImVec2(x + sz * 0.5f, y), ImVec2(x + sz, y + sz - 0.5f), ImVec2(x, y + sz - 0.5f), col32);
2858 		x += sz + spacing;
2859 		draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255));
2860 		ImGui::Dummy(ImVec2((sz + spacing) * 8, (sz + spacing) * 3));
2861 	}
2862 	ImGui::Separator();
2863 	{
2864 		static ImVector<ImVec2> points;
2865 		static bool adding_line = false;
2866 		ImGui::Text("Canvas example");
2867 		if (ImGui::Button("Clear")) points.clear();
2868 		if (points.Size >= 2)
2869 		{
2870 			ImGui::SameLine();
2871 			if (ImGui::Button("Undo"))
2872 			{
2873 				points.pop_back();
2874 				points.pop_back();
2875 			}
2876 		}
2877 		ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
2878 
2879 		// Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
2880 		// However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
2881 		// If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
2882 		ImVec2 canvas_pos = ImGui::GetCursorScreenPos();      // ImDrawList API uses screen coordinates!
2883 		ImVec2 canvas_size = ImGui::GetContentRegionAvail();  // Resize canvas to what's available
2884 		if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
2885 		if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
2886 		draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(50, 50, 50, 255), IM_COL32(50, 50, 60, 255), IM_COL32(60, 60, 70, 255), IM_COL32(50, 50, 60, 255));
2887 		draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255, 255, 255, 255));
2888 
2889 		bool adding_preview = false;
2890 		ImGui::InvisibleButton("canvas", canvas_size);
2891 		ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
2892 		if (adding_line)
2893 		{
2894 			adding_preview = true;
2895 			points.push_back(mouse_pos_in_canvas);
2896 			if (!ImGui::IsMouseDown(0))
2897 				adding_line = adding_preview = false;
2898 		}
2899 		if (ImGui::IsItemHovered())
2900 		{
2901 			if (!adding_line && ImGui::IsMouseClicked(0))
2902 			{
2903 				points.push_back(mouse_pos_in_canvas);
2904 				adding_line = true;
2905 			}
2906 			if (ImGui::IsMouseClicked(1) && !points.empty())
2907 			{
2908 				adding_line = adding_preview = false;
2909 				points.pop_back();
2910 				points.pop_back();
2911 			}
2912 		}
2913 		draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), true);  // clip lines within the canvas (if we resize it, etc.)
2914 		for (int i = 0; i < points.Size - 1; i += 2)
2915 			draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i + 1].x, canvas_pos.y + points[i + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
2916 		draw_list->PopClipRect();
2917 		if (adding_preview)
2918 			points.pop_back();
2919 	}
2920 	ImGui::End();
2921 }
2922 
2923 // Demonstrating creating a simple console window, with scrolling, filtering, completion and history.
2924 // For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
2925 struct ExampleAppConsole
2926 {
2927 	char InputBuf[256];
2928 	ImVector<char*> Items;
2929 	bool ScrollToBottom;
2930 	ImVector<char*> History;
2931 	int HistoryPos;  // -1: new line, 0..History.Size-1 browsing history.
2932 	ImVector<const char*> Commands;
2933 
ExampleAppConsoleExampleAppConsole2934 	ExampleAppConsole()
2935 	{
2936 		ClearLog();
2937 		memset(InputBuf, 0, sizeof(InputBuf));
2938 		HistoryPos = -1;
2939 		Commands.push_back("HELP");
2940 		Commands.push_back("HISTORY");
2941 		Commands.push_back("CLEAR");
2942 		Commands.push_back("CLASSIFY");  // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
2943 		AddLog("Welcome to ImGui!");
2944 	}
~ExampleAppConsoleExampleAppConsole2945 	~ExampleAppConsole()
2946 	{
2947 		ClearLog();
2948 		for (int i = 0; i < History.Size; i++)
2949 			free(History[i]);
2950 	}
2951 
2952 	// Portable helpers
StricmpExampleAppConsole2953 	static int Stricmp(const char* str1, const char* str2)
2954 	{
2955 		int d;
2956 		while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1)
2957 		{
2958 			str1++;
2959 			str2++;
2960 		}
2961 		return d;
2962 	}
StrnicmpExampleAppConsole2963 	static int Strnicmp(const char* str1, const char* str2, int n)
2964 	{
2965 		int d = 0;
2966 		while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1)
2967 		{
2968 			str1++;
2969 			str2++;
2970 			n--;
2971 		}
2972 		return d;
2973 	}
StrdupExampleAppConsole2974 	static char* Strdup(const char* str)
2975 	{
2976 		size_t len = strlen(str) + 1;
2977 		void* buff = malloc(len);
2978 		return (char*)memcpy(buff, (const void*)str, len);
2979 	}
2980 
ClearLogExampleAppConsole2981 	void ClearLog()
2982 	{
2983 		for (int i = 0; i < Items.Size; i++)
2984 			free(Items[i]);
2985 		Items.clear();
2986 		ScrollToBottom = true;
2987 	}
2988 
AddLogExampleAppConsole2989 	void AddLog(const char* fmt, ...) IM_FMTARGS(2)
2990 	{
2991 		// FIXME-OPT
2992 		char buf[1024];
2993 		va_list args;
2994 		va_start(args, fmt);
2995 		vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
2996 		buf[IM_ARRAYSIZE(buf) - 1] = 0;
2997 		va_end(args);
2998 		Items.push_back(Strdup(buf));
2999 		ScrollToBottom = true;
3000 	}
3001 
DrawExampleAppConsole3002 	void Draw(const char* title, bool* p_open)
3003 	{
3004 		ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
3005 		if (!ImGui::Begin(title, p_open))
3006 		{
3007 			ImGui::End();
3008 			return;
3009 		}
3010 
3011 		// As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar.
3012 		// Here we create a context menu only available from the title bar.
3013 		if (ImGui::BeginPopupContextItem())
3014 		{
3015 			if (ImGui::MenuItem("Close"))
3016 				*p_open = false;
3017 			ImGui::EndPopup();
3018 		}
3019 
3020 		ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
3021 		ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
3022 
3023 		// TODO: display items starting from the bottom
3024 
3025 		if (ImGui::SmallButton("Add Dummy Text"))
3026 		{
3027 			AddLog("%d some text", Items.Size);
3028 			AddLog("some more text");
3029 			AddLog("display very important message here!");
3030 		}
3031 		ImGui::SameLine();
3032 		if (ImGui::SmallButton("Add Dummy Error"))
3033 		{
3034 			AddLog("[error] something went wrong");
3035 		}
3036 		ImGui::SameLine();
3037 		if (ImGui::SmallButton("Clear"))
3038 		{
3039 			ClearLog();
3040 		}
3041 		ImGui::SameLine();
3042 		bool copy_to_clipboard = ImGui::SmallButton("Copy");
3043 		ImGui::SameLine();
3044 		if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
3045 		//static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
3046 
3047 		ImGui::Separator();
3048 
3049 		ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
3050 		static ImGuiTextFilter filter;
3051 		filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
3052 		ImGui::PopStyleVar();
3053 		ImGui::Separator();
3054 
3055 		const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();              // 1 separator, 1 input text
3056 		ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar);  // Leave room for 1 separator + 1 InputText
3057 		if (ImGui::BeginPopupContextWindow())
3058 		{
3059 			if (ImGui::Selectable("Clear")) ClearLog();
3060 			ImGui::EndPopup();
3061 		}
3062 
3063 		// Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
3064 		// NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
3065 		// You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements.
3066 		// To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
3067 		//     ImGuiListClipper clipper(Items.Size);
3068 		//     while (clipper.Step())
3069 		//         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
3070 		// However take note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list.
3071 		// A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter,
3072 		// and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code!
3073 		// If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list.
3074 		ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1));  // Tighten spacing
3075 		if (copy_to_clipboard)
3076 			ImGui::LogToClipboard();
3077 		ImVec4 col_default_text = ImGui::GetStyleColorVec4(ImGuiCol_Text);
3078 		for (int i = 0; i < Items.Size; i++)
3079 		{
3080 			const char* item = Items[i];
3081 			if (!filter.PassFilter(item))
3082 				continue;
3083 			ImVec4 col = col_default_text;
3084 			if (strstr(item, "[error]"))
3085 				col = ImColor(1.0f, 0.4f, 0.4f, 1.0f);
3086 			else if (strncmp(item, "# ", 2) == 0)
3087 				col = ImColor(1.0f, 0.78f, 0.58f, 1.0f);
3088 			ImGui::PushStyleColor(ImGuiCol_Text, col);
3089 			ImGui::TextUnformatted(item);
3090 			ImGui::PopStyleColor();
3091 		}
3092 		if (copy_to_clipboard)
3093 			ImGui::LogFinish();
3094 		if (ScrollToBottom)
3095 			ImGui::SetScrollHere();
3096 		ScrollToBottom = false;
3097 		ImGui::PopStyleVar();
3098 		ImGui::EndChild();
3099 		ImGui::Separator();
3100 
3101 		// Command-line
3102 		bool reclaim_focus = false;
3103 		if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
3104 		{
3105 			char* input_end = InputBuf + strlen(InputBuf);
3106 			while (input_end > InputBuf && input_end[-1] == ' ')
3107 			{
3108 				input_end--;
3109 			}
3110 			*input_end = 0;
3111 			if (InputBuf[0])
3112 				ExecCommand(InputBuf);
3113 			strcpy(InputBuf, "");
3114 			reclaim_focus = true;
3115 		}
3116 
3117 		// Demonstrate keeping focus on the input box
3118 		ImGui::SetItemDefaultFocus();
3119 		if (reclaim_focus)
3120 			ImGui::SetKeyboardFocusHere(-1);  // Auto focus previous widget
3121 
3122 		ImGui::End();
3123 	}
3124 
ExecCommandExampleAppConsole3125 	void ExecCommand(const char* command_line)
3126 	{
3127 		AddLog("# %s\n", command_line);
3128 
3129 		// Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal.
3130 		HistoryPos = -1;
3131 		for (int i = History.Size - 1; i >= 0; i--)
3132 			if (Stricmp(History[i], command_line) == 0)
3133 			{
3134 				free(History[i]);
3135 				History.erase(History.begin() + i);
3136 				break;
3137 			}
3138 		History.push_back(Strdup(command_line));
3139 
3140 		// Process command
3141 		if (Stricmp(command_line, "CLEAR") == 0)
3142 		{
3143 			ClearLog();
3144 		}
3145 		else if (Stricmp(command_line, "HELP") == 0)
3146 		{
3147 			AddLog("Commands:");
3148 			for (int i = 0; i < Commands.Size; i++)
3149 				AddLog("- %s", Commands[i]);
3150 		}
3151 		else if (Stricmp(command_line, "HISTORY") == 0)
3152 		{
3153 			int first = History.Size - 10;
3154 			for (int i = first > 0 ? first : 0; i < History.Size; i++)
3155 				AddLog("%3d: %s\n", i, History[i]);
3156 		}
3157 		else
3158 		{
3159 			AddLog("Unknown command: '%s'\n", command_line);
3160 		}
3161 	}
3162 
TextEditCallbackStubExampleAppConsole3163 	static int TextEditCallbackStub(ImGuiTextEditCallbackData* data)  // In C++11 you are better off using lambdas for this sort of forwarding callbacks
3164 	{
3165 		ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
3166 		return console->TextEditCallback(data);
3167 	}
3168 
TextEditCallbackExampleAppConsole3169 	int TextEditCallback(ImGuiTextEditCallbackData* data)
3170 	{
3171 		//AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
3172 		switch (data->EventFlag)
3173 		{
3174 			case ImGuiInputTextFlags_CallbackCompletion:
3175 			{
3176 				// Example of TEXT COMPLETION
3177 
3178 				// Locate beginning of current word
3179 				const char* word_end = data->Buf + data->CursorPos;
3180 				const char* word_start = word_end;
3181 				while (word_start > data->Buf)
3182 				{
3183 					const char c = word_start[-1];
3184 					if (c == ' ' || c == '\t' || c == ',' || c == ';')
3185 						break;
3186 					word_start--;
3187 				}
3188 
3189 				// Build a list of candidates
3190 				ImVector<const char*> candidates;
3191 				for (int i = 0; i < Commands.Size; i++)
3192 					if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0)
3193 						candidates.push_back(Commands[i]);
3194 
3195 				if (candidates.Size == 0)
3196 				{
3197 					// No match
3198 					AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start);
3199 				}
3200 				else if (candidates.Size == 1)
3201 				{
3202 					// Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
3203 					data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
3204 					data->InsertChars(data->CursorPos, candidates[0]);
3205 					data->InsertChars(data->CursorPos, " ");
3206 				}
3207 				else
3208 				{
3209 					// Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
3210 					int match_len = (int)(word_end - word_start);
3211 					for (;;)
3212 					{
3213 						int c = 0;
3214 						bool all_candidates_matches = true;
3215 						for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
3216 							if (i == 0)
3217 								c = toupper(candidates[i][match_len]);
3218 							else if (c == 0 || c != toupper(candidates[i][match_len]))
3219 								all_candidates_matches = false;
3220 						if (!all_candidates_matches)
3221 							break;
3222 						match_len++;
3223 					}
3224 
3225 					if (match_len > 0)
3226 					{
3227 						data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
3228 						data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
3229 					}
3230 
3231 					// List matches
3232 					AddLog("Possible matches:\n");
3233 					for (int i = 0; i < candidates.Size; i++)
3234 						AddLog("- %s\n", candidates[i]);
3235 				}
3236 
3237 				break;
3238 			}
3239 			case ImGuiInputTextFlags_CallbackHistory:
3240 			{
3241 				// Example of HISTORY
3242 				const int prev_history_pos = HistoryPos;
3243 				if (data->EventKey == ImGuiKey_UpArrow)
3244 				{
3245 					if (HistoryPos == -1)
3246 						HistoryPos = History.Size - 1;
3247 					else if (HistoryPos > 0)
3248 						HistoryPos--;
3249 				}
3250 				else if (data->EventKey == ImGuiKey_DownArrow)
3251 				{
3252 					if (HistoryPos != -1)
3253 						if (++HistoryPos >= History.Size)
3254 							HistoryPos = -1;
3255 				}
3256 
3257 				// A better implementation would preserve the data on the current input line along with cursor position.
3258 				if (prev_history_pos != HistoryPos)
3259 				{
3260 					data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : "");
3261 					data->BufDirty = true;
3262 				}
3263 			}
3264 		}
3265 		return 0;
3266 	}
3267 };
3268 
ShowExampleAppConsole(bool * p_open)3269 static void ShowExampleAppConsole(bool* p_open)
3270 {
3271 	static ExampleAppConsole console;
3272 	console.Draw("Example: Console", p_open);
3273 }
3274 
3275 // Usage:
3276 //  static ExampleAppLog my_log;
3277 //  my_log.AddLog("Hello %d world\n", 123);
3278 //  my_log.Draw("title");
3279 struct ExampleAppLog
3280 {
3281 	ImGuiTextBuffer Buf;
3282 	ImGuiTextFilter Filter;
3283 	ImVector<int> LineOffsets;  // Index to lines offset
3284 	bool ScrollToBottom;
3285 
ClearExampleAppLog3286 	void Clear()
3287 	{
3288 		Buf.clear();
3289 		LineOffsets.clear();
3290 	}
3291 
AddLogExampleAppLog3292 	void AddLog(const char* fmt, ...) IM_FMTARGS(2)
3293 	{
3294 		int old_size = Buf.size();
3295 		va_list args;
3296 		va_start(args, fmt);
3297 		Buf.appendfv(fmt, args);
3298 		va_end(args);
3299 		for (int new_size = Buf.size(); old_size < new_size; old_size++)
3300 			if (Buf[old_size] == '\n')
3301 				LineOffsets.push_back(old_size);
3302 		ScrollToBottom = true;
3303 	}
3304 
DrawExampleAppLog3305 	void Draw(const char* title, bool* p_open = NULL)
3306 	{
3307 		ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
3308 		ImGui::Begin(title, p_open);
3309 		if (ImGui::Button("Clear")) Clear();
3310 		ImGui::SameLine();
3311 		bool copy = ImGui::Button("Copy");
3312 		ImGui::SameLine();
3313 		Filter.Draw("Filter", -100.0f);
3314 		ImGui::Separator();
3315 		ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
3316 		if (copy) ImGui::LogToClipboard();
3317 
3318 		if (Filter.IsActive())
3319 		{
3320 			const char* buf_begin = Buf.begin();
3321 			const char* line = buf_begin;
3322 			for (int line_no = 0; line != NULL; line_no++)
3323 			{
3324 				const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
3325 				if (Filter.PassFilter(line, line_end))
3326 					ImGui::TextUnformatted(line, line_end);
3327 				line = line_end && line_end[1] ? line_end + 1 : NULL;
3328 			}
3329 		}
3330 		else
3331 		{
3332 			ImGui::TextUnformatted(Buf.begin());
3333 		}
3334 
3335 		if (ScrollToBottom)
3336 			ImGui::SetScrollHere(1.0f);
3337 		ScrollToBottom = false;
3338 		ImGui::EndChild();
3339 		ImGui::End();
3340 	}
3341 };
3342 
3343 // Demonstrate creating a simple log window with basic filtering.
ShowExampleAppLog(bool * p_open)3344 static void ShowExampleAppLog(bool* p_open)
3345 {
3346 	static ExampleAppLog log;
3347 
3348 	// Demo: add random items (unless Ctrl is held)
3349 	static float last_time = -1.0f;
3350 	float time = ImGui::GetTime();
3351 	if (time - last_time >= 0.20f && !ImGui::GetIO().KeyCtrl)
3352 	{
3353 		const char* random_words[] = {"system", "info", "warning", "error", "fatal", "notice", "log"};
3354 		log.AddLog("[%s] Hello, time is %.1f, frame count is %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, ImGui::GetFrameCount());
3355 		last_time = time;
3356 	}
3357 
3358 	log.Draw("Example: Log", p_open);
3359 }
3360 
3361 // Demonstrate create a window with multiple child windows.
ShowExampleAppLayout(bool * p_open)3362 static void ShowExampleAppLayout(bool* p_open)
3363 {
3364 	ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
3365 	if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar))
3366 	{
3367 		if (ImGui::BeginMenuBar())
3368 		{
3369 			if (ImGui::BeginMenu("File"))
3370 			{
3371 				if (ImGui::MenuItem("Close")) *p_open = false;
3372 				ImGui::EndMenu();
3373 			}
3374 			ImGui::EndMenuBar();
3375 		}
3376 
3377 		// left
3378 		static int selected = 0;
3379 		ImGui::BeginChild("left pane", ImVec2(150, 0), true);
3380 		for (int i = 0; i < 100; i++)
3381 		{
3382 			char label[128];
3383 			sprintf(label, "MyObject %d", i);
3384 			if (ImGui::Selectable(label, selected == i))
3385 				selected = i;
3386 		}
3387 		ImGui::EndChild();
3388 		ImGui::SameLine();
3389 
3390 		// right
3391 		ImGui::BeginGroup();
3392 		ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing()));  // Leave room for 1 line below us
3393 		ImGui::Text("MyObject: %d", selected);
3394 		ImGui::Separator();
3395 		ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
3396 		ImGui::EndChild();
3397 		if (ImGui::Button("Revert"))
3398 		{
3399 		}
3400 		ImGui::SameLine();
3401 		if (ImGui::Button("Save"))
3402 		{
3403 		}
3404 		ImGui::EndGroup();
3405 	}
3406 	ImGui::End();
3407 }
3408 
3409 // Demonstrate create a simple property editor.
ShowExampleAppPropertyEditor(bool * p_open)3410 static void ShowExampleAppPropertyEditor(bool* p_open)
3411 {
3412 	ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
3413 	if (!ImGui::Begin("Example: Property editor", p_open))
3414 	{
3415 		ImGui::End();
3416 		return;
3417 	}
3418 
3419 	ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API.");
3420 
3421 	ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
3422 	ImGui::Columns(2);
3423 	ImGui::Separator();
3424 
3425 	struct funcs
3426 	{
3427 		static void ShowDummyObject(const char* prefix, int uid)
3428 		{
3429 			ImGui::PushID(uid);                // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
3430 			ImGui::AlignTextToFramePadding();  // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
3431 			bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
3432 			ImGui::NextColumn();
3433 			ImGui::AlignTextToFramePadding();
3434 			ImGui::Text("my sailor is rich");
3435 			ImGui::NextColumn();
3436 			if (node_open)
3437 			{
3438 				static float dummy_members[8] = {0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f};
3439 				for (int i = 0; i < 8; i++)
3440 				{
3441 					ImGui::PushID(i);  // Use field index as identifier.
3442 					if (i < 2)
3443 					{
3444 						ShowDummyObject("Child", 424242);
3445 					}
3446 					else
3447 					{
3448 						ImGui::AlignTextToFramePadding();
3449 						// Here we use a Selectable (instead of Text) to highlight on hover
3450 						//ImGui::Text("Field_%d", i);
3451 						char label[32];
3452 						sprintf(label, "Field_%d", i);
3453 						ImGui::Bullet();
3454 						ImGui::Selectable(label);
3455 						ImGui::NextColumn();
3456 						ImGui::PushItemWidth(-1);
3457 						if (i >= 5)
3458 							ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
3459 						else
3460 							ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
3461 						ImGui::PopItemWidth();
3462 						ImGui::NextColumn();
3463 					}
3464 					ImGui::PopID();
3465 				}
3466 				ImGui::TreePop();
3467 			}
3468 			ImGui::PopID();
3469 		}
3470 	};
3471 
3472 	// Iterate dummy objects with dummy members (all the same data)
3473 	for (int obj_i = 0; obj_i < 3; obj_i++)
3474 		funcs::ShowDummyObject("Object", obj_i);
3475 
3476 	ImGui::Columns(1);
3477 	ImGui::Separator();
3478 	ImGui::PopStyleVar();
3479 	ImGui::End();
3480 }
3481 
3482 // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
ShowExampleAppLongText(bool * p_open)3483 static void ShowExampleAppLongText(bool* p_open)
3484 {
3485 	ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
3486 	if (!ImGui::Begin("Example: Long text display", p_open))
3487 	{
3488 		ImGui::End();
3489 		return;
3490 	}
3491 
3492 	static int test_type = 0;
3493 	static ImGuiTextBuffer log;
3494 	static int lines = 0;
3495 	ImGui::Text("Printing unusually long amount of text.");
3496 	ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
3497 	ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
3498 	if (ImGui::Button("Clear"))
3499 	{
3500 		log.clear();
3501 		lines = 0;
3502 	}
3503 	ImGui::SameLine();
3504 	if (ImGui::Button("Add 1000 lines"))
3505 	{
3506 		for (int i = 0; i < 1000; i++)
3507 			log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
3508 		lines += 1000;
3509 	}
3510 	ImGui::BeginChild("Log");
3511 	switch (test_type)
3512 	{
3513 		case 0:
3514 			// Single call to TextUnformatted() with a big buffer
3515 			ImGui::TextUnformatted(log.begin(), log.end());
3516 			break;
3517 		case 1:
3518 		{
3519 			// Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
3520 			ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
3521 			ImGuiListClipper clipper(lines);
3522 			while (clipper.Step())
3523 				for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
3524 					ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
3525 			ImGui::PopStyleVar();
3526 			break;
3527 		}
3528 		case 2:
3529 			// Multiple calls to Text(), not clipped (slow)
3530 			ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
3531 			for (int i = 0; i < lines; i++)
3532 				ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
3533 			ImGui::PopStyleVar();
3534 			break;
3535 	}
3536 	ImGui::EndChild();
3537 	ImGui::End();
3538 }
3539 
3540 // End of Demo code
3541 #else
3542 
ShowDemoWindow(bool *)3543 void ImGui::ShowDemoWindow(bool*) {}
ShowUserGuide()3544 void ImGui::ShowUserGuide() {}
ShowStyleEditor(ImGuiStyle *)3545 void ImGui::ShowStyleEditor(ImGuiStyle*) {}
3546 
3547 #endif
3548