imgui_demo.cpp 123 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641
  1. // dear imgui, v1.50
  2. // (demo code)
  3. // Message to the person tempted to delete this file when integrating ImGui into their code base:
  4. // Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to.
  5. // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowTestWindow().
  6. // During development, you can call ImGui::ShowTestWindow() in your code to learn about various features of ImGui.
  7. // Removing this file from your project is hindering your access to documentation, likely leading you to poorer usage of the library.
  8. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
  9. #define _CRT_SECURE_NO_WARNINGS
  10. #endif
  11. #include "imgui.h"
  12. #include <ctype.h> // toupper, isprint
  13. #include <math.h> // sqrtf, powf, cosf, sinf, floorf, ceilf
  14. #include <stdio.h> // vsnprintf, sscanf, printf
  15. #include <stdlib.h> // NULL, malloc, free, qsort, atoi
  16. #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
  17. #include <stddef.h> // intptr_t
  18. #else
  19. #include <stdint.h> // intptr_t
  20. #endif
  21. #ifdef _MSC_VER
  22. #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
  23. #define snprintf _snprintf
  24. #endif
  25. #ifdef __clang__
  26. #pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
  27. #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)
  28. #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
  29. #pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal
  30. #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.
  31. #if __has_warning("-Wreserved-id-macro")
  32. #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier //
  33. #endif
  34. #elif defined(__GNUC__)
  35. #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
  36. #pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure)
  37. #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
  38. #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
  39. #if (__GNUC__ >= 6)
  40. #pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on github.
  41. #endif
  42. #endif
  43. // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
  44. #ifdef _WIN32
  45. #define IM_NEWLINE "\r\n"
  46. #else
  47. #define IM_NEWLINE "\n"
  48. #endif
  49. #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
  50. #define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B))
  51. //-----------------------------------------------------------------------------
  52. // DEMO CODE
  53. //-----------------------------------------------------------------------------
  54. #ifndef IMGUI_DISABLE_TEST_WINDOWS
  55. static void ShowExampleAppConsole(bool* p_open);
  56. static void ShowExampleAppLog(bool* p_open);
  57. static void ShowExampleAppLayout(bool* p_open);
  58. static void ShowExampleAppPropertyEditor(bool* p_open);
  59. static void ShowExampleAppLongText(bool* p_open);
  60. static void ShowExampleAppAutoResize(bool* p_open);
  61. static void ShowExampleAppConstrainedResize(bool* p_open);
  62. static void ShowExampleAppFixedOverlay(bool* p_open);
  63. static void ShowExampleAppManipulatingWindowTitle(bool* p_open);
  64. static void ShowExampleAppCustomRendering(bool* p_open);
  65. static void ShowExampleAppMainMenuBar();
  66. static void ShowExampleMenuFile();
  67. static void ShowHelpMarker(const char* desc)
  68. {
  69. ImGui::TextDisabled("(?)");
  70. if (ImGui::IsItemHovered())
  71. {
  72. ImGui::BeginTooltip();
  73. ImGui::PushTextWrapPos(450.0f);
  74. ImGui::TextUnformatted(desc);
  75. ImGui::PopTextWrapPos();
  76. ImGui::EndTooltip();
  77. }
  78. }
  79. void ImGui::ShowUserGuide()
  80. {
  81. ImGui::BulletText("Double-click on title bar to collapse window.");
  82. ImGui::BulletText("Click and drag on lower right corner to resize window.");
  83. ImGui::BulletText("Click and drag on any empty space to move window.");
  84. ImGui::BulletText("Mouse Wheel to scroll.");
  85. if (ImGui::GetIO().FontAllowUserScaling)
  86. ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
  87. ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
  88. ImGui::BulletText("CTRL+Click on a slider or drag box to input text.");
  89. ImGui::BulletText(
  90. "While editing text:\n"
  91. "- Hold SHIFT or use mouse to select text\n"
  92. "- CTRL+Left/Right to word jump\n"
  93. "- CTRL+A or double-click to select all\n"
  94. "- CTRL+X,CTRL+C,CTRL+V clipboard\n"
  95. "- CTRL+Z,CTRL+Y undo/redo\n"
  96. "- ESCAPE to revert\n"
  97. "- You can apply arithmetic operators +,*,/ on numerical values.\n"
  98. " Use +- to subtract.\n");
  99. }
  100. // Demonstrate most ImGui features (big function!)
  101. void ImGui::ShowTestWindow(bool* p_open)
  102. {
  103. // Examples apps
  104. static bool show_app_main_menu_bar = false;
  105. static bool show_app_console = false;
  106. static bool show_app_log = false;
  107. static bool show_app_layout = false;
  108. static bool show_app_property_editor = false;
  109. static bool show_app_long_text = false;
  110. static bool show_app_auto_resize = false;
  111. static bool show_app_constrained_resize = false;
  112. static bool show_app_fixed_overlay = false;
  113. static bool show_app_manipulating_window_title = false;
  114. static bool show_app_custom_rendering = false;
  115. static bool show_app_style_editor = false;
  116. static bool show_app_metrics = false;
  117. static bool show_app_about = false;
  118. if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
  119. if (show_app_console) ShowExampleAppConsole(&show_app_console);
  120. if (show_app_log) ShowExampleAppLog(&show_app_log);
  121. if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
  122. if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor);
  123. if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
  124. if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
  125. if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize);
  126. if (show_app_fixed_overlay) ShowExampleAppFixedOverlay(&show_app_fixed_overlay);
  127. if (show_app_manipulating_window_title) ShowExampleAppManipulatingWindowTitle(&show_app_manipulating_window_title);
  128. if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);
  129. if (show_app_metrics) ImGui::ShowMetricsWindow(&show_app_metrics);
  130. if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }
  131. if (show_app_about)
  132. {
  133. ImGui::Begin("About ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize);
  134. ImGui::Text("dear imgui, %s", ImGui::GetVersion());
  135. ImGui::Separator();
  136. ImGui::Text("By Omar Cornut and all github contributors.");
  137. ImGui::Text("ImGui is licensed under the MIT License, see LICENSE for more information.");
  138. ImGui::End();
  139. }
  140. static bool no_titlebar = false;
  141. static bool no_border = true;
  142. static bool no_resize = false;
  143. static bool no_move = false;
  144. static bool no_scrollbar = false;
  145. static bool no_collapse = false;
  146. static bool no_menu = false;
  147. // Demonstrate the various window flags. Typically you would just use the default.
  148. ImGuiWindowFlags window_flags = 0;
  149. if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
  150. if (!no_border) window_flags |= ImGuiWindowFlags_ShowBorders;
  151. if (no_resize) window_flags |= ImGuiWindowFlags_NoResize;
  152. if (no_move) window_flags |= ImGuiWindowFlags_NoMove;
  153. if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
  154. if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
  155. if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar;
  156. ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver);
  157. if (!ImGui::Begin("ImGui Demo", p_open, window_flags))
  158. {
  159. // Early out if the window is collapsed, as an optimization.
  160. ImGui::End();
  161. return;
  162. }
  163. //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels
  164. ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels
  165. ImGui::Text("Dear ImGui says hello.");
  166. // Menu
  167. if (ImGui::BeginMenuBar())
  168. {
  169. if (ImGui::BeginMenu("Menu"))
  170. {
  171. ShowExampleMenuFile();
  172. ImGui::EndMenu();
  173. }
  174. if (ImGui::BeginMenu("Examples"))
  175. {
  176. ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
  177. ImGui::MenuItem("Console", NULL, &show_app_console);
  178. ImGui::MenuItem("Log", NULL, &show_app_log);
  179. ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
  180. ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
  181. ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
  182. ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
  183. ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
  184. ImGui::MenuItem("Simple overlay", NULL, &show_app_fixed_overlay);
  185. ImGui::MenuItem("Manipulating window title", NULL, &show_app_manipulating_window_title);
  186. ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
  187. ImGui::EndMenu();
  188. }
  189. if (ImGui::BeginMenu("Help"))
  190. {
  191. ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
  192. ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
  193. ImGui::MenuItem("About ImGui", NULL, &show_app_about);
  194. ImGui::EndMenu();
  195. }
  196. ImGui::EndMenuBar();
  197. }
  198. ImGui::Spacing();
  199. if (ImGui::CollapsingHeader("Help"))
  200. {
  201. ImGui::TextWrapped("This window is being created by the ShowTestWindow() function. Please refer to the code for programming reference.\n\nUser Guide:");
  202. ImGui::ShowUserGuide();
  203. }
  204. if (ImGui::CollapsingHeader("Window options"))
  205. {
  206. ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
  207. ImGui::Checkbox("No border", &no_border); ImGui::SameLine(300);
  208. ImGui::Checkbox("No resize", &no_resize);
  209. ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
  210. ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
  211. ImGui::Checkbox("No collapse", &no_collapse);
  212. ImGui::Checkbox("No menu", &no_menu);
  213. if (ImGui::TreeNode("Style"))
  214. {
  215. ImGui::ShowStyleEditor();
  216. ImGui::TreePop();
  217. }
  218. if (ImGui::TreeNode("Logging"))
  219. {
  220. 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.");
  221. ImGui::LogButtons();
  222. ImGui::TreePop();
  223. }
  224. }
  225. if (ImGui::CollapsingHeader("Widgets"))
  226. {
  227. if (ImGui::TreeNode("Trees"))
  228. {
  229. if (ImGui::TreeNode("Basic trees"))
  230. {
  231. for (int i = 0; i < 5; i++)
  232. if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
  233. {
  234. ImGui::Text("blah blah");
  235. ImGui::SameLine();
  236. if (ImGui::SmallButton("print")) printf("Child %d pressed", i);
  237. ImGui::TreePop();
  238. }
  239. ImGui::TreePop();
  240. }
  241. if (ImGui::TreeNode("Advanced, with Selectable nodes"))
  242. {
  243. 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.");
  244. static bool align_label_with_current_x_position = false;
  245. ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
  246. ImGui::Text("Hello!");
  247. if (align_label_with_current_x_position)
  248. ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
  249. 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.
  250. 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.
  251. ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents.
  252. for (int i = 0; i < 6; i++)
  253. {
  254. // Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
  255. ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);
  256. if (i < 3)
  257. {
  258. // Node
  259. bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
  260. if (ImGui::IsItemClicked())
  261. node_clicked = i;
  262. if (node_open)
  263. {
  264. ImGui::Text("Blah blah\nBlah Blah");
  265. ImGui::TreePop();
  266. }
  267. }
  268. else
  269. {
  270. // 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().
  271. ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, "Selectable Leaf %d", i);
  272. if (ImGui::IsItemClicked())
  273. node_clicked = i;
  274. }
  275. }
  276. if (node_clicked != -1)
  277. {
  278. // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
  279. if (ImGui::GetIO().KeyCtrl)
  280. selection_mask ^= (1 << node_clicked); // CTRL+click to toggle
  281. 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
  282. selection_mask = (1 << node_clicked); // Click to single-select
  283. }
  284. ImGui::PopStyleVar();
  285. if (align_label_with_current_x_position)
  286. ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
  287. ImGui::TreePop();
  288. }
  289. ImGui::TreePop();
  290. }
  291. if (ImGui::TreeNode("Collapsing Headers"))
  292. {
  293. static bool closable_group = true;
  294. if (ImGui::CollapsingHeader("Header"))
  295. {
  296. ImGui::Checkbox("Enable extra group", &closable_group);
  297. for (int i = 0; i < 5; i++)
  298. ImGui::Text("Some content %d", i);
  299. }
  300. if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
  301. {
  302. for (int i = 0; i < 5; i++)
  303. ImGui::Text("More content %d", i);
  304. }
  305. ImGui::TreePop();
  306. }
  307. if (ImGui::TreeNode("Bullets"))
  308. {
  309. ImGui::BulletText("Bullet point 1");
  310. ImGui::BulletText("Bullet point 2\nOn multiple lines");
  311. ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
  312. ImGui::Bullet(); ImGui::SmallButton("Button");
  313. ImGui::TreePop();
  314. }
  315. if (ImGui::TreeNode("Colored Text"))
  316. {
  317. // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
  318. ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
  319. ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
  320. ImGui::TextDisabled("Disabled");
  321. ImGui::TreePop();
  322. }
  323. if (ImGui::TreeNode("Word Wrapping"))
  324. {
  325. // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
  326. 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.");
  327. ImGui::Spacing();
  328. static float wrap_width = 200.0f;
  329. ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
  330. ImGui::Text("Test paragraph 1:");
  331. ImVec2 pos = ImGui::GetCursorScreenPos();
  332. 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));
  333. ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
  334. 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);
  335. ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
  336. ImGui::PopTextWrapPos();
  337. ImGui::Text("Test paragraph 2:");
  338. pos = ImGui::GetCursorScreenPos();
  339. 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));
  340. ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
  341. ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh");
  342. ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
  343. ImGui::PopTextWrapPos();
  344. ImGui::TreePop();
  345. }
  346. if (ImGui::TreeNode("UTF-8 Text"))
  347. {
  348. // UTF-8 test with Japanese characters
  349. // (needs a suitable font, try Arial Unicode or M+ fonts http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html)
  350. // Most compiler appears to support UTF-8 in source code (with Visual Studio you need to save your file as 'UTF-8 without signature')
  351. // However for the sake for maximum portability here we are *not* including raw UTF-8 character in this source file, instead we encode the string with hexadecimal constants.
  352. // In your own application be reasonable and use UTF-8 in source or retrieve the data from file system!
  353. // Note that characters values are preserved even if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.
  354. 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.");
  355. ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
  356. ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
  357. static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
  358. ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
  359. ImGui::TreePop();
  360. }
  361. if (ImGui::TreeNode("Images"))
  362. {
  363. 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!");
  364. ImVec2 tex_screen_pos = ImGui::GetCursorScreenPos();
  365. float tex_w = (float)ImGui::GetIO().Fonts->TexWidth;
  366. float tex_h = (float)ImGui::GetIO().Fonts->TexHeight;
  367. ImTextureID tex_id = ImGui::GetIO().Fonts->TexID;
  368. ImGui::Text("%.0fx%.0f", tex_w, tex_h);
  369. ImGui::Image(tex_id, ImVec2(tex_w, tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
  370. if (ImGui::IsItemHovered())
  371. {
  372. ImGui::BeginTooltip();
  373. float focus_sz = 32.0f;
  374. float focus_x = ImGui::GetMousePos().x - tex_screen_pos.x - focus_sz * 0.5f; if (focus_x < 0.0f) focus_x = 0.0f; else if (focus_x > tex_w - focus_sz) focus_x = tex_w - focus_sz;
  375. float focus_y = ImGui::GetMousePos().y - tex_screen_pos.y - focus_sz * 0.5f; if (focus_y < 0.0f) focus_y = 0.0f; else if (focus_y > tex_h - focus_sz) focus_y = tex_h - focus_sz;
  376. ImGui::Text("Min: (%.2f, %.2f)", focus_x, focus_y);
  377. ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz);
  378. ImVec2 uv0 = ImVec2((focus_x) / tex_w, (focus_y) / tex_h);
  379. ImVec2 uv1 = ImVec2((focus_x + focus_sz) / tex_w, (focus_y + focus_sz) / tex_h);
  380. ImGui::Image(tex_id, ImVec2(128,128), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128));
  381. ImGui::EndTooltip();
  382. }
  383. ImGui::TextWrapped("And now some textured buttons..");
  384. static int pressed_count = 0;
  385. for (int i = 0; i < 8; i++)
  386. {
  387. ImGui::PushID(i);
  388. int frame_padding = -1 + i; // -1 = uses default padding
  389. if (ImGui::ImageButton(tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/tex_w,32/tex_h), frame_padding, ImColor(0,0,0,255)))
  390. pressed_count += 1;
  391. ImGui::PopID();
  392. ImGui::SameLine();
  393. }
  394. ImGui::NewLine();
  395. ImGui::Text("Pressed %d times.", pressed_count);
  396. ImGui::TreePop();
  397. }
  398. if (ImGui::TreeNode("Selectables"))
  399. {
  400. if (ImGui::TreeNode("Basic"))
  401. {
  402. static bool selected[4] = { false, true, false, false };
  403. ImGui::Selectable("1. I am selectable", &selected[0]);
  404. ImGui::Selectable("2. I am selectable", &selected[1]);
  405. ImGui::Text("3. I am not selectable");
  406. ImGui::Selectable("4. I am selectable", &selected[2]);
  407. if (ImGui::Selectable("5. I am double clickable", selected[3], ImGuiSelectableFlags_AllowDoubleClick))
  408. if (ImGui::IsMouseDoubleClicked(0))
  409. selected[3] = !selected[3];
  410. ImGui::TreePop();
  411. }
  412. if (ImGui::TreeNode("Rendering more text into the same block"))
  413. {
  414. static bool selected[3] = { false, false, false };
  415. ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
  416. ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
  417. ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
  418. ImGui::TreePop();
  419. }
  420. if (ImGui::TreeNode("In columns"))
  421. {
  422. ImGui::Columns(3, NULL, false);
  423. static bool selected[16] = { 0 };
  424. for (int i = 0; i < 16; i++)
  425. {
  426. char label[32]; sprintf(label, "Item %d", i);
  427. if (ImGui::Selectable(label, &selected[i])) {}
  428. ImGui::NextColumn();
  429. }
  430. ImGui::Columns(1);
  431. ImGui::TreePop();
  432. }
  433. if (ImGui::TreeNode("Grid"))
  434. {
  435. static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };
  436. for (int i = 0; i < 16; i++)
  437. {
  438. ImGui::PushID(i);
  439. if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50)))
  440. {
  441. int x = i % 4, y = i / 4;
  442. if (x > 0) selected[i - 1] ^= 1;
  443. if (x < 3) selected[i + 1] ^= 1;
  444. if (y > 0) selected[i - 4] ^= 1;
  445. if (y < 3) selected[i + 4] ^= 1;
  446. }
  447. if ((i % 4) < 3) ImGui::SameLine();
  448. ImGui::PopID();
  449. }
  450. ImGui::TreePop();
  451. }
  452. ImGui::TreePop();
  453. }
  454. if (ImGui::TreeNode("Filtered Text Input"))
  455. {
  456. static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
  457. static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
  458. static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
  459. static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
  460. static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
  461. struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
  462. static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
  463. ImGui::Text("Password input");
  464. static char bufpass[64] = "password123";
  465. ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
  466. ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
  467. ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
  468. ImGui::TreePop();
  469. }
  470. if (ImGui::TreeNode("Multi-line Text Input"))
  471. {
  472. static bool read_only = false;
  473. static char text[1024*16] =
  474. "/*\n"
  475. " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
  476. " the hexadecimal encoding of one offending instruction,\n"
  477. " more formally, the invalid operand with locked CMPXCHG8B\n"
  478. " instruction bug, is a design flaw in the majority of\n"
  479. " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
  480. " processors (all in the P5 microarchitecture).\n"
  481. "*/\n\n"
  482. "label:\n"
  483. "\tlock cmpxchg8b eax\n";
  484. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
  485. ImGui::Checkbox("Read-only", &read_only);
  486. ImGui::PopStyleVar();
  487. ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0));
  488. ImGui::TreePop();
  489. }
  490. static bool a=false;
  491. if (ImGui::Button("Button")) { printf("Clicked\n"); a ^= 1; }
  492. if (a)
  493. {
  494. ImGui::SameLine();
  495. ImGui::Text("Thanks for clicking me!");
  496. }
  497. static bool check = true;
  498. ImGui::Checkbox("checkbox", &check);
  499. static int e = 0;
  500. ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
  501. ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
  502. ImGui::RadioButton("radio c", &e, 2);
  503. // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
  504. for (int i = 0; i < 7; i++)
  505. {
  506. if (i > 0) ImGui::SameLine();
  507. ImGui::PushID(i);
  508. ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(i/7.0f, 0.6f, 0.6f));
  509. ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(i/7.0f, 0.7f, 0.7f));
  510. ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(i/7.0f, 0.8f, 0.8f));
  511. ImGui::Button("Click");
  512. ImGui::PopStyleColor(3);
  513. ImGui::PopID();
  514. }
  515. ImGui::Text("Hover over me");
  516. if (ImGui::IsItemHovered())
  517. ImGui::SetTooltip("I am a tooltip");
  518. ImGui::SameLine();
  519. ImGui::Text("- or me");
  520. if (ImGui::IsItemHovered())
  521. {
  522. ImGui::BeginTooltip();
  523. ImGui::Text("I am a fancy tooltip");
  524. static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
  525. ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
  526. ImGui::EndTooltip();
  527. }
  528. // Testing IMGUI_ONCE_UPON_A_FRAME macro
  529. //for (int i = 0; i < 5; i++)
  530. //{
  531. // IMGUI_ONCE_UPON_A_FRAME
  532. // {
  533. // ImGui::Text("This will be displayed only once.");
  534. // }
  535. //}
  536. ImGui::Separator();
  537. ImGui::LabelText("label", "Value");
  538. static int item = 1;
  539. ImGui::Combo("combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Combo using values packed in a single constant string (for really quick combo)
  540. const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK" };
  541. static int item2 = -1;
  542. ImGui::Combo("combo scroll", &item2, 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.
  543. {
  544. static char str0[128] = "Hello, world!";
  545. static int i0=123;
  546. static float f0=0.001f;
  547. ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
  548. ImGui::SameLine(); ShowHelpMarker("Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n");
  549. ImGui::InputInt("input int", &i0);
  550. ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
  551. ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);
  552. static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
  553. ImGui::InputFloat3("input float3", vec4a);
  554. }
  555. {
  556. static int i1=50, i2=42;
  557. ImGui::DragInt("drag int", &i1, 1);
  558. ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
  559. ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%.0f%%");
  560. static float f1=1.00f, f2=0.0067f;
  561. ImGui::DragFloat("drag float", &f1, 0.005f);
  562. ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
  563. }
  564. {
  565. static int i1=0;
  566. ImGui::SliderInt("slider int", &i1, -1, 3);
  567. ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
  568. static float f1=0.123f, f2=0.0f;
  569. ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
  570. ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f);
  571. static float angle = 0.0f;
  572. ImGui::SliderAngle("slider angle", &angle);
  573. }
  574. static float col1[3] = { 1.0f,0.0f,0.2f };
  575. static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
  576. ImGui::ColorEdit3("color 1", col1);
  577. ImGui::SameLine(); ShowHelpMarker("Click on the colored square to change edit mode.\nCTRL+click on individual component to input value.\n");
  578. ImGui::ColorEdit4("color 2", col2);
  579. const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
  580. static int listbox_item_current = 1;
  581. ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
  582. //static int listbox_item_current2 = 2;
  583. //ImGui::PushItemWidth(-1);
  584. //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
  585. //ImGui::PopItemWidth();
  586. if (ImGui::TreeNode("Range Widgets"))
  587. {
  588. ImGui::Unindent();
  589. static float begin = 10, end = 90;
  590. static int begin_i = 100, end_i = 1000;
  591. ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%");
  592. ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %.0f units", "Max: %.0f units");
  593. ImGui::Indent();
  594. ImGui::TreePop();
  595. }
  596. if (ImGui::TreeNode("Multi-component Widgets"))
  597. {
  598. ImGui::Unindent();
  599. static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
  600. static int vec4i[4] = { 1, 5, 100, 255 };
  601. ImGui::InputFloat2("input float2", vec4f);
  602. ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
  603. ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
  604. ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
  605. ImGui::InputInt2("input int2", vec4i);
  606. ImGui::SliderInt2("slider int2", vec4i, 0, 255);
  607. ImGui::Spacing();
  608. ImGui::InputFloat3("input float3", vec4f);
  609. ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
  610. ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
  611. ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
  612. ImGui::InputInt3("input int3", vec4i);
  613. ImGui::SliderInt3("slider int3", vec4i, 0, 255);
  614. ImGui::Spacing();
  615. ImGui::InputFloat4("input float4", vec4f);
  616. ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
  617. ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
  618. ImGui::InputInt4("input int4", vec4i);
  619. ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
  620. ImGui::SliderInt4("slider int4", vec4i, 0, 255);
  621. ImGui::Indent();
  622. ImGui::TreePop();
  623. }
  624. if (ImGui::TreeNode("Vertical Sliders"))
  625. {
  626. ImGui::Unindent();
  627. const float spacing = 4;
  628. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
  629. static int int_value = 0;
  630. ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5);
  631. ImGui::SameLine();
  632. static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
  633. ImGui::PushID("set1");
  634. for (int i = 0; i < 7; i++)
  635. {
  636. if (i > 0) ImGui::SameLine();
  637. ImGui::PushID(i);
  638. ImGui::PushStyleColor(ImGuiCol_FrameBg, ImColor::HSV(i/7.0f, 0.5f, 0.5f));
  639. ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImColor::HSV(i/7.0f, 0.6f, 0.5f));
  640. ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImColor::HSV(i/7.0f, 0.7f, 0.5f));
  641. ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImColor::HSV(i/7.0f, 0.9f, 0.9f));
  642. ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, "");
  643. if (ImGui::IsItemActive() || ImGui::IsItemHovered())
  644. ImGui::SetTooltip("%.3f", values[i]);
  645. ImGui::PopStyleColor(4);
  646. ImGui::PopID();
  647. }
  648. ImGui::PopID();
  649. ImGui::SameLine();
  650. ImGui::PushID("set2");
  651. static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
  652. const int rows = 3;
  653. const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows);
  654. for (int nx = 0; nx < 4; nx++)
  655. {
  656. if (nx > 0) ImGui::SameLine();
  657. ImGui::BeginGroup();
  658. for (int ny = 0; ny < rows; ny++)
  659. {
  660. ImGui::PushID(nx*rows+ny);
  661. ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
  662. if (ImGui::IsItemActive() || ImGui::IsItemHovered())
  663. ImGui::SetTooltip("%.3f", values2[nx]);
  664. ImGui::PopID();
  665. }
  666. ImGui::EndGroup();
  667. }
  668. ImGui::PopID();
  669. ImGui::SameLine();
  670. ImGui::PushID("set3");
  671. for (int i = 0; i < 4; i++)
  672. {
  673. if (i > 0) ImGui::SameLine();
  674. ImGui::PushID(i);
  675. ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
  676. ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
  677. ImGui::PopStyleVar();
  678. ImGui::PopID();
  679. }
  680. ImGui::PopID();
  681. ImGui::PopStyleVar();
  682. ImGui::Indent();
  683. ImGui::TreePop();
  684. }
  685. }
  686. if (ImGui::CollapsingHeader("Graphs widgets"))
  687. {
  688. static bool animate = true;
  689. ImGui::Checkbox("Animate", &animate);
  690. static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
  691. ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
  692. // Create a dummy array of contiguous float values to plot
  693. // 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.
  694. static float values[90] = { 0 };
  695. static int values_offset = 0;
  696. if (animate)
  697. {
  698. static float refresh_time = ImGui::GetTime(); // Create dummy data at fixed 60 hz rate for the demo
  699. for (; ImGui::GetTime() > refresh_time + 1.0f/60.0f; refresh_time += 1.0f/60.0f)
  700. {
  701. static float phase = 0.0f;
  702. values[values_offset] = cosf(phase);
  703. values_offset = (values_offset+1) % IM_ARRAYSIZE(values);
  704. phase += 0.10f*values_offset;
  705. }
  706. }
  707. ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
  708. ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80));
  709. // Use functions to generate output
  710. // 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.
  711. struct Funcs
  712. {
  713. static float Sin(void*, int i) { return sinf(i * 0.1f); }
  714. static float Saw(void*, int i) { return (i & 1) ? 1.0f : 0.0f; }
  715. };
  716. static int func_type = 0, display_count = 70;
  717. ImGui::Separator();
  718. ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth();
  719. ImGui::SameLine();
  720. ImGui::SliderInt("Sample count", &display_count, 1, 400);
  721. float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
  722. ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
  723. ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
  724. ImGui::Separator();
  725. // Animate a simple progress bar
  726. static float progress = 0.0f, progress_dir = 1.0f;
  727. if (animate)
  728. {
  729. progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
  730. if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
  731. if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
  732. }
  733. // 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.
  734. ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f));
  735. ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
  736. ImGui::Text("Progress Bar");
  737. float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
  738. char buf[32];
  739. sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753);
  740. ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf);
  741. }
  742. if (ImGui::CollapsingHeader("Layout"))
  743. {
  744. if (ImGui::TreeNode("Child regions"))
  745. {
  746. ImGui::Text("Without border");
  747. static int line = 50;
  748. bool goto_line = ImGui::Button("Goto");
  749. ImGui::SameLine();
  750. ImGui::PushItemWidth(100);
  751. goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
  752. ImGui::PopItemWidth();
  753. ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f,300), false, ImGuiWindowFlags_HorizontalScrollbar);
  754. for (int i = 0; i < 100; i++)
  755. {
  756. ImGui::Text("%04d: scrollable region", i);
  757. if (goto_line && line == i)
  758. ImGui::SetScrollHere();
  759. }
  760. if (goto_line && line >= 100)
  761. ImGui::SetScrollHere();
  762. ImGui::EndChild();
  763. ImGui::SameLine();
  764. ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, 5.0f);
  765. ImGui::BeginChild("Sub2", ImVec2(0,300), true);
  766. ImGui::Text("With border");
  767. ImGui::Columns(2);
  768. for (int i = 0; i < 100; i++)
  769. {
  770. if (i == 50)
  771. ImGui::NextColumn();
  772. char buf[32];
  773. sprintf(buf, "%08x", i*5731);
  774. ImGui::Button(buf, ImVec2(-1.0f, 0.0f));
  775. }
  776. ImGui::EndChild();
  777. ImGui::PopStyleVar();
  778. ImGui::TreePop();
  779. }
  780. if (ImGui::TreeNode("Widgets Width"))
  781. {
  782. static float f = 0.0f;
  783. ImGui::Text("PushItemWidth(100)");
  784. ImGui::SameLine(); ShowHelpMarker("Fixed width.");
  785. ImGui::PushItemWidth(100);
  786. ImGui::DragFloat("float##1", &f);
  787. ImGui::PopItemWidth();
  788. ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
  789. ImGui::SameLine(); ShowHelpMarker("Half of window width.");
  790. ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
  791. ImGui::DragFloat("float##2", &f);
  792. ImGui::PopItemWidth();
  793. ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
  794. ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
  795. ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
  796. ImGui::DragFloat("float##3", &f);
  797. ImGui::PopItemWidth();
  798. ImGui::Text("PushItemWidth(-100)");
  799. ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100");
  800. ImGui::PushItemWidth(-100);
  801. ImGui::DragFloat("float##4", &f);
  802. ImGui::PopItemWidth();
  803. ImGui::Text("PushItemWidth(-1)");
  804. ImGui::SameLine(); ShowHelpMarker("Align to right edge");
  805. ImGui::PushItemWidth(-1);
  806. ImGui::DragFloat("float##5", &f);
  807. ImGui::PopItemWidth();
  808. ImGui::TreePop();
  809. }
  810. if (ImGui::TreeNode("Basic Horizontal Layout"))
  811. {
  812. ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
  813. // Text
  814. ImGui::Text("Two items: Hello"); ImGui::SameLine();
  815. ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
  816. // Adjust spacing
  817. ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
  818. ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
  819. // Button
  820. ImGui::AlignFirstTextHeightToWidgets();
  821. ImGui::Text("Normal buttons"); ImGui::SameLine();
  822. ImGui::Button("Banana"); ImGui::SameLine();
  823. ImGui::Button("Apple"); ImGui::SameLine();
  824. ImGui::Button("Corniflower");
  825. // Button
  826. ImGui::Text("Small buttons"); ImGui::SameLine();
  827. ImGui::SmallButton("Like this one"); ImGui::SameLine();
  828. ImGui::Text("can fit within a text block.");
  829. // Aligned to arbitrary position. Easy/cheap column.
  830. ImGui::Text("Aligned");
  831. ImGui::SameLine(150); ImGui::Text("x=150");
  832. ImGui::SameLine(300); ImGui::Text("x=300");
  833. ImGui::Text("Aligned");
  834. ImGui::SameLine(150); ImGui::SmallButton("x=150");
  835. ImGui::SameLine(300); ImGui::SmallButton("x=300");
  836. // Checkbox
  837. static bool c1=false,c2=false,c3=false,c4=false;
  838. ImGui::Checkbox("My", &c1); ImGui::SameLine();
  839. ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
  840. ImGui::Checkbox("Is", &c3); ImGui::SameLine();
  841. ImGui::Checkbox("Rich", &c4);
  842. // Various
  843. static float f0=1.0f, f1=2.0f, f2=3.0f;
  844. ImGui::PushItemWidth(80);
  845. const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
  846. static int item = -1;
  847. ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
  848. ImGui::SliderFloat("X", &f0, 0.0f,5.0f); ImGui::SameLine();
  849. ImGui::SliderFloat("Y", &f1, 0.0f,5.0f); ImGui::SameLine();
  850. ImGui::SliderFloat("Z", &f2, 0.0f,5.0f);
  851. ImGui::PopItemWidth();
  852. ImGui::PushItemWidth(80);
  853. ImGui::Text("Lists:");
  854. static int selection[4] = { 0, 1, 2, 3 };
  855. for (int i = 0; i < 4; i++)
  856. {
  857. if (i > 0) ImGui::SameLine();
  858. ImGui::PushID(i);
  859. ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
  860. ImGui::PopID();
  861. //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
  862. }
  863. ImGui::PopItemWidth();
  864. // Dummy
  865. ImVec2 sz(30,30);
  866. ImGui::Button("A", sz); ImGui::SameLine();
  867. ImGui::Dummy(sz); ImGui::SameLine();
  868. ImGui::Button("B", sz);
  869. ImGui::TreePop();
  870. }
  871. if (ImGui::TreeNode("Groups"))
  872. {
  873. 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.)");
  874. ImGui::BeginGroup();
  875. {
  876. ImGui::BeginGroup();
  877. ImGui::Button("AAA");
  878. ImGui::SameLine();
  879. ImGui::Button("BBB");
  880. ImGui::SameLine();
  881. ImGui::BeginGroup();
  882. ImGui::Button("CCC");
  883. ImGui::Button("DDD");
  884. ImGui::EndGroup();
  885. if (ImGui::IsItemHovered())
  886. ImGui::SetTooltip("Group hovered");
  887. ImGui::SameLine();
  888. ImGui::Button("EEE");
  889. ImGui::EndGroup();
  890. }
  891. // Capture the group size and create widgets using the same size
  892. ImVec2 size = ImGui::GetItemRectSize();
  893. const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
  894. ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
  895. ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
  896. ImGui::SameLine();
  897. ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
  898. ImGui::EndGroup();
  899. ImGui::SameLine();
  900. ImGui::Button("LEVERAGE\nBUZZWORD", size);
  901. ImGui::SameLine();
  902. ImGui::ListBoxHeader("List", size);
  903. ImGui::Selectable("Selected", true);
  904. ImGui::Selectable("Not Selected", false);
  905. ImGui::ListBoxFooter();
  906. ImGui::TreePop();
  907. }
  908. if (ImGui::TreeNode("Text Baseline Alignment"))
  909. {
  910. 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)");
  911. ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
  912. ImGui::Text("Hello\nWorld"); ImGui::SameLine();
  913. ImGui::Text("Banana");
  914. ImGui::Text("Banana"); ImGui::SameLine();
  915. ImGui::Text("Hello\nWorld"); ImGui::SameLine();
  916. ImGui::Text("One\nTwo\nThree");
  917. ImGui::Button("HOP##1"); ImGui::SameLine();
  918. ImGui::Text("Banana"); ImGui::SameLine();
  919. ImGui::Text("Hello\nWorld"); ImGui::SameLine();
  920. ImGui::Text("Banana");
  921. ImGui::Button("HOP##2"); ImGui::SameLine();
  922. ImGui::Text("Hello\nWorld"); ImGui::SameLine();
  923. ImGui::Text("Banana");
  924. ImGui::Button("TEST##1"); ImGui::SameLine();
  925. ImGui::Text("TEST"); ImGui::SameLine();
  926. ImGui::SmallButton("TEST##2");
  927. ImGui::AlignFirstTextHeightToWidgets(); // If your line starts with text, call this to align it to upcoming widgets.
  928. ImGui::Text("Text aligned to Widget"); ImGui::SameLine();
  929. ImGui::Button("Widget##1"); ImGui::SameLine();
  930. ImGui::Text("Widget"); ImGui::SameLine();
  931. ImGui::SmallButton("Widget##2");
  932. // Tree
  933. const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
  934. ImGui::Button("Button##1");
  935. ImGui::SameLine(0.0f, spacing);
  936. if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data
  937. ImGui::AlignFirstTextHeightToWidgets(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit).
  938. 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.
  939. ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
  940. if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data
  941. // Bullet
  942. ImGui::Button("Button##3");
  943. ImGui::SameLine(0.0f, spacing);
  944. ImGui::BulletText("Bullet text");
  945. ImGui::AlignFirstTextHeightToWidgets();
  946. ImGui::BulletText("Node");
  947. ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
  948. ImGui::TreePop();
  949. }
  950. if (ImGui::TreeNode("Scrolling"))
  951. {
  952. ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)");
  953. static bool track = true;
  954. static int track_line = 50, scroll_to_px = 200;
  955. ImGui::Checkbox("Track", &track);
  956. ImGui::PushItemWidth(100);
  957. ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line %.0f");
  958. bool scroll_to = ImGui::Button("Scroll To");
  959. ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "y = %.0f px");
  960. ImGui::PopItemWidth();
  961. if (scroll_to) track = false;
  962. for (int i = 0; i < 5; i++)
  963. {
  964. if (i > 0) ImGui::SameLine();
  965. ImGui::BeginGroup();
  966. ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
  967. ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
  968. if (scroll_to)
  969. ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
  970. for (int line = 0; line < 100; line++)
  971. {
  972. if (track && line == track_line)
  973. {
  974. ImGui::TextColored(ImColor(255,255,0), "Line %d", line);
  975. ImGui::SetScrollHere(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
  976. }
  977. else
  978. {
  979. ImGui::Text("Line %d", line);
  980. }
  981. }
  982. ImGui::EndChild();
  983. ImGui::EndGroup();
  984. }
  985. ImGui::TreePop();
  986. }
  987. if (ImGui::TreeNode("Horizontal Scrolling"))
  988. {
  989. ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.");
  990. ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
  991. static int lines = 7;
  992. ImGui::SliderInt("Lines", &lines, 1, 15);
  993. ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
  994. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
  995. ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetItemsLineHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
  996. for (int line = 0; line < lines; line++)
  997. {
  998. // 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
  999. // 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)
  1000. int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
  1001. for (int n = 0; n < num_buttons; n++)
  1002. {
  1003. if (n > 0) ImGui::SameLine();
  1004. ImGui::PushID(n + line * 1000);
  1005. char num_buf[16];
  1006. const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : (sprintf(num_buf, "%d", n), num_buf);
  1007. float hue = n*0.05f;
  1008. ImGui::PushStyleColor(ImGuiCol_Button, ImColor::HSV(hue, 0.6f, 0.6f));
  1009. ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImColor::HSV(hue, 0.7f, 0.7f));
  1010. ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImColor::HSV(hue, 0.8f, 0.8f));
  1011. ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
  1012. ImGui::PopStyleColor(3);
  1013. ImGui::PopID();
  1014. }
  1015. }
  1016. ImGui::EndChild();
  1017. ImGui::PopStyleVar(2);
  1018. float scroll_x_delta = 0.0f;
  1019. ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f;
  1020. ImGui::SameLine(); ImGui::Text("Scroll from code"); ImGui::SameLine();
  1021. ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f;
  1022. if (scroll_x_delta != 0.0f)
  1023. {
  1024. 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)
  1025. ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
  1026. ImGui::End();
  1027. }
  1028. ImGui::TreePop();
  1029. }
  1030. if (ImGui::TreeNode("Clipping"))
  1031. {
  1032. static ImVec2 size(100, 100), offset(50, 20);
  1033. 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.");
  1034. ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f");
  1035. ImGui::TextWrapped("(Click and drag)");
  1036. ImVec2 pos = ImGui::GetCursorScreenPos();
  1037. ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y);
  1038. ImGui::InvisibleButton("##dummy", size);
  1039. if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
  1040. ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255));
  1041. ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
  1042. ImGui::TreePop();
  1043. }
  1044. }
  1045. if (ImGui::CollapsingHeader("Popups & Modal windows"))
  1046. {
  1047. if (ImGui::TreeNode("Popups"))
  1048. {
  1049. ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
  1050. static int selected_fish = -1;
  1051. const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
  1052. static bool toggles[] = { true, false, false, false, false };
  1053. // Simple selection popup
  1054. // (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)
  1055. if (ImGui::Button("Select.."))
  1056. ImGui::OpenPopup("select");
  1057. ImGui::SameLine();
  1058. ImGui::Text(selected_fish == -1 ? "<None>" : names[selected_fish]);
  1059. if (ImGui::BeginPopup("select"))
  1060. {
  1061. ImGui::Text("Aquarium");
  1062. ImGui::Separator();
  1063. for (int i = 0; i < IM_ARRAYSIZE(names); i++)
  1064. if (ImGui::Selectable(names[i]))
  1065. selected_fish = i;
  1066. ImGui::EndPopup();
  1067. }
  1068. // Showing a menu with toggles
  1069. if (ImGui::Button("Toggle.."))
  1070. ImGui::OpenPopup("toggle");
  1071. if (ImGui::BeginPopup("toggle"))
  1072. {
  1073. for (int i = 0; i < IM_ARRAYSIZE(names); i++)
  1074. ImGui::MenuItem(names[i], "", &toggles[i]);
  1075. if (ImGui::BeginMenu("Sub-menu"))
  1076. {
  1077. ImGui::MenuItem("Click me");
  1078. ImGui::EndMenu();
  1079. }
  1080. ImGui::Separator();
  1081. ImGui::Text("Tooltip here");
  1082. if (ImGui::IsItemHovered())
  1083. ImGui::SetTooltip("I am a tooltip over a popup");
  1084. if (ImGui::Button("Stacked Popup"))
  1085. ImGui::OpenPopup("another popup");
  1086. if (ImGui::BeginPopup("another popup"))
  1087. {
  1088. for (int i = 0; i < IM_ARRAYSIZE(names); i++)
  1089. ImGui::MenuItem(names[i], "", &toggles[i]);
  1090. if (ImGui::BeginMenu("Sub-menu"))
  1091. {
  1092. ImGui::MenuItem("Click me");
  1093. ImGui::EndMenu();
  1094. }
  1095. ImGui::EndPopup();
  1096. }
  1097. ImGui::EndPopup();
  1098. }
  1099. if (ImGui::Button("Popup Menu.."))
  1100. ImGui::OpenPopup("FilePopup");
  1101. if (ImGui::BeginPopup("FilePopup"))
  1102. {
  1103. ShowExampleMenuFile();
  1104. ImGui::EndPopup();
  1105. }
  1106. ImGui::Spacing();
  1107. ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
  1108. ImGui::Separator();
  1109. // 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.
  1110. // 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
  1111. // 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.
  1112. ImGui::PushID("foo");
  1113. ImGui::MenuItem("Menu item", "CTRL+M");
  1114. if (ImGui::BeginMenu("Menu inside a regular window"))
  1115. {
  1116. ShowExampleMenuFile();
  1117. ImGui::EndMenu();
  1118. }
  1119. ImGui::PopID();
  1120. ImGui::Separator();
  1121. ImGui::TreePop();
  1122. }
  1123. if (ImGui::TreeNode("Context menus"))
  1124. {
  1125. static float value = 0.5f;
  1126. ImGui::Text("Value = %.3f (<-- right-click here)", value);
  1127. if (ImGui::BeginPopupContextItem("item context menu"))
  1128. {
  1129. if (ImGui::Selectable("Set to zero")) value = 0.0f;
  1130. if (ImGui::Selectable("Set to PI")) value = 3.1415f;
  1131. ImGui::EndPopup();
  1132. }
  1133. static ImVec4 color = ImColor(0.8f, 0.5f, 1.0f, 1.0f);
  1134. ImGui::ColorButton(color);
  1135. if (ImGui::BeginPopupContextItem("color context menu"))
  1136. {
  1137. ImGui::Text("Edit color");
  1138. ImGui::ColorEdit3("##edit", (float*)&color);
  1139. if (ImGui::Button("Close"))
  1140. ImGui::CloseCurrentPopup();
  1141. ImGui::EndPopup();
  1142. }
  1143. ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
  1144. ImGui::TreePop();
  1145. }
  1146. if (ImGui::TreeNode("Modals"))
  1147. {
  1148. ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
  1149. if (ImGui::Button("Delete.."))
  1150. ImGui::OpenPopup("Delete?");
  1151. if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
  1152. {
  1153. ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
  1154. ImGui::Separator();
  1155. //static int dummy_i = 0;
  1156. //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
  1157. static bool dont_ask_me_next_time = false;
  1158. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
  1159. ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
  1160. ImGui::PopStyleVar();
  1161. if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
  1162. ImGui::SameLine();
  1163. if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
  1164. ImGui::EndPopup();
  1165. }
  1166. if (ImGui::Button("Stacked modals.."))
  1167. ImGui::OpenPopup("Stacked 1");
  1168. if (ImGui::BeginPopupModal("Stacked 1"))
  1169. {
  1170. ImGui::Text("Hello from Stacked The First");
  1171. if (ImGui::Button("Another one.."))
  1172. ImGui::OpenPopup("Stacked 2");
  1173. if (ImGui::BeginPopupModal("Stacked 2"))
  1174. {
  1175. ImGui::Text("Hello from Stacked The Second");
  1176. if (ImGui::Button("Close"))
  1177. ImGui::CloseCurrentPopup();
  1178. ImGui::EndPopup();
  1179. }
  1180. if (ImGui::Button("Close"))
  1181. ImGui::CloseCurrentPopup();
  1182. ImGui::EndPopup();
  1183. }
  1184. ImGui::TreePop();
  1185. }
  1186. }
  1187. if (ImGui::CollapsingHeader("Columns"))
  1188. {
  1189. // Basic columns
  1190. if (ImGui::TreeNode("Basic"))
  1191. {
  1192. ImGui::Text("Without border:");
  1193. ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border
  1194. ImGui::Separator();
  1195. for (int n = 0; n < 14; n++)
  1196. {
  1197. char label[32];
  1198. sprintf(label, "Item %d", n);
  1199. if (ImGui::Selectable(label)) {}
  1200. //if (ImGui::Button(label, ImVec2(-1,0))) {}
  1201. ImGui::NextColumn();
  1202. }
  1203. ImGui::Columns(1);
  1204. ImGui::Separator();
  1205. ImGui::Text("With border:");
  1206. ImGui::Columns(4, "mycolumns"); // 4-ways, with border
  1207. ImGui::Separator();
  1208. ImGui::Text("ID"); ImGui::NextColumn();
  1209. ImGui::Text("Name"); ImGui::NextColumn();
  1210. ImGui::Text("Path"); ImGui::NextColumn();
  1211. ImGui::Text("Flags"); ImGui::NextColumn();
  1212. ImGui::Separator();
  1213. const char* names[3] = { "One", "Two", "Three" };
  1214. const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
  1215. static int selected = -1;
  1216. for (int i = 0; i < 3; i++)
  1217. {
  1218. char label[32];
  1219. sprintf(label, "%04d", i);
  1220. if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
  1221. selected = i;
  1222. ImGui::NextColumn();
  1223. ImGui::Text(names[i]); ImGui::NextColumn();
  1224. ImGui::Text(paths[i]); ImGui::NextColumn();
  1225. ImGui::Text("...."); ImGui::NextColumn();
  1226. }
  1227. ImGui::Columns(1);
  1228. ImGui::Separator();
  1229. ImGui::TreePop();
  1230. }
  1231. // Scrolling columns
  1232. /*
  1233. if (ImGui::TreeNode("Scrolling"))
  1234. {
  1235. ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
  1236. ImGui::Columns(3);
  1237. ImGui::Text("ID"); ImGui::NextColumn();
  1238. ImGui::Text("Name"); ImGui::NextColumn();
  1239. ImGui::Text("Path"); ImGui::NextColumn();
  1240. ImGui::Columns(1);
  1241. ImGui::Separator();
  1242. ImGui::EndChild();
  1243. ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
  1244. ImGui::Columns(3);
  1245. for (int i = 0; i < 10; i++)
  1246. {
  1247. ImGui::Text("%04d", i); ImGui::NextColumn();
  1248. ImGui::Text("Foobar"); ImGui::NextColumn();
  1249. ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
  1250. }
  1251. ImGui::Columns(1);
  1252. ImGui::EndChild();
  1253. ImGui::TreePop();
  1254. }
  1255. */
  1256. // Create multiple items in a same cell before switching to next column
  1257. if (ImGui::TreeNode("Mixed items"))
  1258. {
  1259. ImGui::Columns(3, "mixed");
  1260. ImGui::Separator();
  1261. ImGui::Text("Hello");
  1262. ImGui::Button("Banana");
  1263. ImGui::NextColumn();
  1264. ImGui::Text("ImGui");
  1265. ImGui::Button("Apple");
  1266. static float foo = 1.0f;
  1267. ImGui::InputFloat("red", &foo, 0.05f, 0, 3);
  1268. ImGui::Text("An extra line here.");
  1269. ImGui::NextColumn();
  1270. ImGui::Text("Sailor");
  1271. ImGui::Button("Corniflower");
  1272. static float bar = 1.0f;
  1273. ImGui::InputFloat("blue", &bar, 0.05f, 0, 3);
  1274. ImGui::NextColumn();
  1275. if (ImGui::CollapsingHeader("Category A")) ImGui::Text("Blah blah blah"); ImGui::NextColumn();
  1276. if (ImGui::CollapsingHeader("Category B")) ImGui::Text("Blah blah blah"); ImGui::NextColumn();
  1277. if (ImGui::CollapsingHeader("Category C")) ImGui::Text("Blah blah blah"); ImGui::NextColumn();
  1278. ImGui::Columns(1);
  1279. ImGui::Separator();
  1280. ImGui::TreePop();
  1281. }
  1282. // Word wrapping
  1283. if (ImGui::TreeNode("Word-wrapping"))
  1284. {
  1285. ImGui::Columns(2, "word-wrapping");
  1286. ImGui::Separator();
  1287. ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
  1288. ImGui::TextWrapped("Hello Left");
  1289. ImGui::NextColumn();
  1290. ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
  1291. ImGui::TextWrapped("Hello Right");
  1292. ImGui::Columns(1);
  1293. ImGui::Separator();
  1294. ImGui::TreePop();
  1295. }
  1296. if (ImGui::TreeNode("Borders"))
  1297. {
  1298. static bool h_borders = true;
  1299. static bool v_borders = true;
  1300. ImGui::Checkbox("horizontal", &h_borders);
  1301. ImGui::SameLine();
  1302. ImGui::Checkbox("vertical", &v_borders);
  1303. ImGui::Columns(4, NULL, v_borders);
  1304. if (h_borders) ImGui::Separator();
  1305. for (int i = 0; i < 8; i++)
  1306. {
  1307. ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
  1308. ImGui::NextColumn();
  1309. }
  1310. ImGui::Columns(1);
  1311. if (h_borders) ImGui::Separator();
  1312. ImGui::TreePop();
  1313. }
  1314. bool node_open = ImGui::TreeNode("Tree within single cell");
  1315. ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell.\nThere's no storage of state per-cell.");
  1316. if (node_open)
  1317. {
  1318. ImGui::Columns(2, "tree items");
  1319. ImGui::Separator();
  1320. if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
  1321. if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
  1322. ImGui::Columns(1);
  1323. ImGui::Separator();
  1324. ImGui::TreePop();
  1325. }
  1326. }
  1327. if (ImGui::CollapsingHeader("Filtering"))
  1328. {
  1329. static ImGuiTextFilter filter;
  1330. ImGui::Text("Filter usage:\n"
  1331. " \"\" display all lines\n"
  1332. " \"xxx\" display lines containing \"xxx\"\n"
  1333. " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
  1334. " \"-xxx\" hide lines containing \"xxx\"");
  1335. filter.Draw();
  1336. const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
  1337. for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
  1338. if (filter.PassFilter(lines[i]))
  1339. ImGui::BulletText("%s", lines[i]);
  1340. }
  1341. if (ImGui::CollapsingHeader("Keyboard, Mouse & Focus"))
  1342. {
  1343. if (ImGui::TreeNode("Tabbing"))
  1344. {
  1345. ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
  1346. static char buf[32] = "dummy";
  1347. ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
  1348. ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
  1349. ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
  1350. ImGui::PushAllowKeyboardFocus(false);
  1351. ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
  1352. //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
  1353. ImGui::PopAllowKeyboardFocus();
  1354. ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
  1355. ImGui::TreePop();
  1356. }
  1357. if (ImGui::TreeNode("Focus from code"))
  1358. {
  1359. bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
  1360. bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
  1361. bool focus_3 = ImGui::Button("Focus on 3");
  1362. int has_focus = 0;
  1363. static char buf[128] = "click on a button to set focus";
  1364. if (focus_1) ImGui::SetKeyboardFocusHere();
  1365. ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
  1366. if (ImGui::IsItemActive()) has_focus = 1;
  1367. if (focus_2) ImGui::SetKeyboardFocusHere();
  1368. ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
  1369. if (ImGui::IsItemActive()) has_focus = 2;
  1370. ImGui::PushAllowKeyboardFocus(false);
  1371. if (focus_3) ImGui::SetKeyboardFocusHere();
  1372. ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
  1373. if (ImGui::IsItemActive()) has_focus = 3;
  1374. ImGui::PopAllowKeyboardFocus();
  1375. if (has_focus)
  1376. ImGui::Text("Item with focus: %d", has_focus);
  1377. else
  1378. ImGui::Text("Item with focus: <none>");
  1379. ImGui::TextWrapped("Cursor & selection are preserved when refocusing last used item in code.");
  1380. ImGui::TreePop();
  1381. }
  1382. if (ImGui::TreeNode("Dragging"))
  1383. {
  1384. ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
  1385. ImGui::Button("Drag Me");
  1386. if (ImGui::IsItemActive())
  1387. {
  1388. // Draw a line between the button and the mouse cursor
  1389. ImDrawList* draw_list = ImGui::GetWindowDrawList();
  1390. draw_list->PushClipRectFullScreen();
  1391. draw_list->AddLine(ImGui::CalcItemRectClosestPoint(ImGui::GetIO().MousePos, true, -2.0f), ImGui::GetIO().MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f);
  1392. draw_list->PopClipRect();
  1393. ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
  1394. ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
  1395. ImVec2 mouse_delta = ImGui::GetIO().MouseDelta;
  1396. ImGui::SameLine(); 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);
  1397. }
  1398. ImGui::TreePop();
  1399. }
  1400. if (ImGui::TreeNode("Keyboard & Mouse State"))
  1401. {
  1402. ImGuiIO& io = ImGui::GetIO();
  1403. ImGui::Text("MousePos: (%g, %g)", io.MousePos.x, io.MousePos.y);
  1404. ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
  1405. ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
  1406. ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
  1407. ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
  1408. ImGui::Text("MouseWheel: %.1f", io.MouseWheel);
  1409. ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); }
  1410. ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
  1411. ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
  1412. ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
  1413. ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false");
  1414. ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false");
  1415. ImGui::Text("WantTextInput: %s", io.WantTextInput ? "true" : "false");
  1416. ImGui::Button("Hovering me sets the\nkeyboard capture flag");
  1417. if (ImGui::IsItemHovered())
  1418. ImGui::CaptureKeyboardFromApp(true);
  1419. ImGui::SameLine();
  1420. ImGui::Button("Holding me clears the\nthe keyboard capture flag");
  1421. if (ImGui::IsItemActive())
  1422. ImGui::CaptureKeyboardFromApp(false);
  1423. ImGui::TreePop();
  1424. }
  1425. if (ImGui::TreeNode("Mouse cursors"))
  1426. {
  1427. ImGui::TextWrapped("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. You can also set io.MouseDrawCursor to ask ImGui to render the cursor for you in software.");
  1428. ImGui::Checkbox("io.MouseDrawCursor", &ImGui::GetIO().MouseDrawCursor);
  1429. ImGui::Text("Hover to see mouse cursors:");
  1430. for (int i = 0; i < ImGuiMouseCursor_Count_; i++)
  1431. {
  1432. char label[32];
  1433. sprintf(label, "Mouse cursor %d", i);
  1434. ImGui::Bullet(); ImGui::Selectable(label, false);
  1435. if (ImGui::IsItemHovered())
  1436. ImGui::SetMouseCursor(i);
  1437. }
  1438. ImGui::TreePop();
  1439. }
  1440. }
  1441. ImGui::End();
  1442. }
  1443. void ImGui::ShowStyleEditor(ImGuiStyle* ref)
  1444. {
  1445. ImGuiStyle& style = ImGui::GetStyle();
  1446. // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to the default style)
  1447. const ImGuiStyle default_style; // Default style
  1448. if (ImGui::Button("Revert Style"))
  1449. style = ref ? *ref : default_style;
  1450. if (ref)
  1451. {
  1452. ImGui::SameLine();
  1453. if (ImGui::Button("Save Style"))
  1454. *ref = style;
  1455. }
  1456. ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.55f);
  1457. if (ImGui::TreeNode("Rendering"))
  1458. {
  1459. ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
  1460. ImGui::Checkbox("Anti-aliased shapes", &style.AntiAliasedShapes);
  1461. ImGui::PushItemWidth(100);
  1462. ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f);
  1463. if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f;
  1464. 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.
  1465. ImGui::PopItemWidth();
  1466. ImGui::TreePop();
  1467. }
  1468. if (ImGui::TreeNode("Settings"))
  1469. {
  1470. ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
  1471. ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 16.0f, "%.0f");
  1472. ImGui::SliderFloat("ChildWindowRounding", &style.ChildWindowRounding, 0.0f, 16.0f, "%.0f");
  1473. ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
  1474. ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 16.0f, "%.0f");
  1475. ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
  1476. ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
  1477. ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
  1478. ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
  1479. ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
  1480. ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 16.0f, "%.0f");
  1481. ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
  1482. ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 16.0f, "%.0f");
  1483. ImGui::Text("Alignment");
  1484. ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
  1485. ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content.");
  1486. ImGui::TreePop();
  1487. }
  1488. if (ImGui::TreeNode("Colors"))
  1489. {
  1490. static int output_dest = 0;
  1491. static bool output_only_modified = false;
  1492. if (ImGui::Button("Copy Colors"))
  1493. {
  1494. if (output_dest == 0)
  1495. ImGui::LogToClipboard();
  1496. else
  1497. ImGui::LogToTTY();
  1498. ImGui::LogText("ImGuiStyle& style = ImGui::GetStyle();" IM_NEWLINE);
  1499. for (int i = 0; i < ImGuiCol_COUNT; i++)
  1500. {
  1501. const ImVec4& col = style.Colors[i];
  1502. const char* name = ImGui::GetStyleColName(i);
  1503. if (!output_only_modified || memcmp(&col, (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0)
  1504. ImGui::LogText("style.Colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 22 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
  1505. }
  1506. ImGui::LogFinish();
  1507. }
  1508. ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth();
  1509. ImGui::SameLine(); ImGui::Checkbox("Only Modified Fields", &output_only_modified);
  1510. static ImGuiColorEditMode edit_mode = ImGuiColorEditMode_RGB;
  1511. ImGui::RadioButton("RGB", &edit_mode, ImGuiColorEditMode_RGB);
  1512. ImGui::SameLine();
  1513. ImGui::RadioButton("HSV", &edit_mode, ImGuiColorEditMode_HSV);
  1514. ImGui::SameLine();
  1515. ImGui::RadioButton("HEX", &edit_mode, ImGuiColorEditMode_HEX);
  1516. //ImGui::Text("Tip: Click on colored square to change edit mode.");
  1517. static ImGuiTextFilter filter;
  1518. filter.Draw("Filter colors", 200);
  1519. ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
  1520. ImGui::PushItemWidth(-160);
  1521. ImGui::ColorEditMode(edit_mode);
  1522. for (int i = 0; i < ImGuiCol_COUNT; i++)
  1523. {
  1524. const char* name = ImGui::GetStyleColName(i);
  1525. if (!filter.PassFilter(name))
  1526. continue;
  1527. ImGui::PushID(i);
  1528. ImGui::ColorEdit4(name, (float*)&style.Colors[i], true);
  1529. if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &default_style.Colors[i]), sizeof(ImVec4)) != 0)
  1530. {
  1531. ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : default_style.Colors[i];
  1532. if (ref) { ImGui::SameLine(); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i]; }
  1533. }
  1534. ImGui::PopID();
  1535. }
  1536. ImGui::PopItemWidth();
  1537. ImGui::EndChild();
  1538. ImGui::TreePop();
  1539. }
  1540. if (ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size))
  1541. {
  1542. ImGui::SameLine(); ShowHelpMarker("Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\nbefore calling io.Fonts->GetTex* functions.");
  1543. ImFontAtlas* atlas = ImGui::GetIO().Fonts;
  1544. if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
  1545. {
  1546. 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));
  1547. ImGui::TreePop();
  1548. }
  1549. ImGui::PushItemWidth(100);
  1550. for (int i = 0; i < atlas->Fonts.Size; i++)
  1551. {
  1552. ImFont* font = atlas->Fonts[i];
  1553. ImGui::BulletText("Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size);
  1554. ImGui::TreePush((void*)(intptr_t)i);
  1555. ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font;
  1556. ImGui::PushFont(font);
  1557. ImGui::Text("The quick brown fox jumps over the lazy dog");
  1558. ImGui::PopFont();
  1559. if (ImGui::TreeNode("Details"))
  1560. {
  1561. ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font
  1562. ImGui::SameLine(); 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.)");
  1563. ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
  1564. ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
  1565. ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface));
  1566. for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
  1567. {
  1568. ImFontConfig* cfg = &font->ConfigData[config_i];
  1569. ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
  1570. }
  1571. if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
  1572. {
  1573. // Display all glyphs of the fonts in separate pages of 256 characters
  1574. const ImFont::Glyph* glyph_fallback = font->FallbackGlyph; // Forcefully/dodgily make FindGlyph() return NULL on fallback, which isn't the default behavior.
  1575. font->FallbackGlyph = NULL;
  1576. for (int base = 0; base < 0x10000; base += 256)
  1577. {
  1578. int count = 0;
  1579. for (int n = 0; n < 256; n++)
  1580. count += font->FindGlyph((ImWchar)(base + n)) ? 1 : 0;
  1581. if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph"))
  1582. {
  1583. float cell_spacing = style.ItemSpacing.y;
  1584. ImVec2 cell_size(font->FontSize * 1, font->FontSize * 1);
  1585. ImVec2 base_pos = ImGui::GetCursorScreenPos();
  1586. ImDrawList* draw_list = ImGui::GetWindowDrawList();
  1587. for (int n = 0; n < 256; n++)
  1588. {
  1589. ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing));
  1590. ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y);
  1591. const ImFont::Glyph* glyph = font->FindGlyph((ImWchar)(base+n));;
  1592. draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50));
  1593. 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.
  1594. if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
  1595. {
  1596. ImGui::BeginTooltip();
  1597. ImGui::Text("Codepoint: U+%04X", base+n);
  1598. ImGui::Separator();
  1599. ImGui::Text("XAdvance+1: %.1f", glyph->XAdvance);
  1600. ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
  1601. ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
  1602. ImGui::EndTooltip();
  1603. }
  1604. }
  1605. ImGui::Dummy(ImVec2((cell_size.x + cell_spacing) * 16, (cell_size.y + cell_spacing) * 16));
  1606. ImGui::TreePop();
  1607. }
  1608. }
  1609. font->FallbackGlyph = glyph_fallback;
  1610. ImGui::TreePop();
  1611. }
  1612. ImGui::TreePop();
  1613. }
  1614. ImGui::TreePop();
  1615. }
  1616. static float window_scale = 1.0f;
  1617. ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale only this window
  1618. ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything
  1619. ImGui::PopItemWidth();
  1620. ImGui::SetWindowFontScale(window_scale);
  1621. ImGui::TreePop();
  1622. }
  1623. ImGui::PopItemWidth();
  1624. }
  1625. // Demonstrate creating a fullscreen menu bar and populating it.
  1626. static void ShowExampleAppMainMenuBar()
  1627. {
  1628. if (ImGui::BeginMainMenuBar())
  1629. {
  1630. if (ImGui::BeginMenu("File"))
  1631. {
  1632. ShowExampleMenuFile();
  1633. ImGui::EndMenu();
  1634. }
  1635. if (ImGui::BeginMenu("Edit"))
  1636. {
  1637. if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
  1638. if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item
  1639. ImGui::Separator();
  1640. if (ImGui::MenuItem("Cut", "CTRL+X")) {}
  1641. if (ImGui::MenuItem("Copy", "CTRL+C")) {}
  1642. if (ImGui::MenuItem("Paste", "CTRL+V")) {}
  1643. ImGui::EndMenu();
  1644. }
  1645. ImGui::EndMainMenuBar();
  1646. }
  1647. }
  1648. static void ShowExampleMenuFile()
  1649. {
  1650. ImGui::MenuItem("(dummy menu)", NULL, false, false);
  1651. if (ImGui::MenuItem("New")) {}
  1652. if (ImGui::MenuItem("Open", "Ctrl+O")) {}
  1653. if (ImGui::BeginMenu("Open Recent"))
  1654. {
  1655. ImGui::MenuItem("fish_hat.c");
  1656. ImGui::MenuItem("fish_hat.inl");
  1657. ImGui::MenuItem("fish_hat.h");
  1658. if (ImGui::BeginMenu("More.."))
  1659. {
  1660. ImGui::MenuItem("Hello");
  1661. ImGui::MenuItem("Sailor");
  1662. if (ImGui::BeginMenu("Recurse.."))
  1663. {
  1664. ShowExampleMenuFile();
  1665. ImGui::EndMenu();
  1666. }
  1667. ImGui::EndMenu();
  1668. }
  1669. ImGui::EndMenu();
  1670. }
  1671. if (ImGui::MenuItem("Save", "Ctrl+S")) {}
  1672. if (ImGui::MenuItem("Save As..")) {}
  1673. ImGui::Separator();
  1674. if (ImGui::BeginMenu("Options"))
  1675. {
  1676. static bool enabled = true;
  1677. ImGui::MenuItem("Enabled", "", &enabled);
  1678. ImGui::BeginChild("child", ImVec2(0, 60), true);
  1679. for (int i = 0; i < 10; i++)
  1680. ImGui::Text("Scrolling Text %d", i);
  1681. ImGui::EndChild();
  1682. static float f = 0.5f;
  1683. static int n = 0;
  1684. ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
  1685. ImGui::InputFloat("Input", &f, 0.1f);
  1686. ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
  1687. ImGui::EndMenu();
  1688. }
  1689. if (ImGui::BeginMenu("Colors"))
  1690. {
  1691. for (int i = 0; i < ImGuiCol_COUNT; i++)
  1692. ImGui::MenuItem(ImGui::GetStyleColName((ImGuiCol)i));
  1693. ImGui::EndMenu();
  1694. }
  1695. if (ImGui::BeginMenu("Disabled", false)) // Disabled
  1696. {
  1697. IM_ASSERT(0);
  1698. }
  1699. if (ImGui::MenuItem("Checked", NULL, true)) {}
  1700. if (ImGui::MenuItem("Quit", "Alt+F4")) {}
  1701. }
  1702. // Demonstrate creating a window which gets auto-resized according to its content.
  1703. static void ShowExampleAppAutoResize(bool* p_open)
  1704. {
  1705. if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
  1706. {
  1707. ImGui::End();
  1708. return;
  1709. }
  1710. static int lines = 10;
  1711. 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.");
  1712. ImGui::SliderInt("Number of lines", &lines, 1, 20);
  1713. for (int i = 0; i < lines; i++)
  1714. ImGui::Text("%*sThis is line %d", i*4, "", i); // Pad with space to extend size horizontally
  1715. ImGui::End();
  1716. }
  1717. // Demonstrate creating a window with custom resize constraints.
  1718. static void ShowExampleAppConstrainedResize(bool* p_open)
  1719. {
  1720. struct CustomConstraints // Helper functions to demonstrate programmatic constraints
  1721. {
  1722. static void Square(ImGuiSizeConstraintCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }
  1723. static void Step(ImGuiSizeConstraintCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
  1724. };
  1725. static int type = 0;
  1726. if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only
  1727. if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only
  1728. if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
  1729. if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(400, FLT_MAX)); // Width 300-400
  1730. if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square
  1731. if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step
  1732. if (ImGui::Begin("Example: Constrained Resize", p_open))
  1733. {
  1734. const char* desc[] =
  1735. {
  1736. "Resize vertical only",
  1737. "Resize horizontal only",
  1738. "Width > 100, Height > 100",
  1739. "Width 300-400",
  1740. "Custom: Always Square",
  1741. "Custom: Fixed Steps (100)",
  1742. };
  1743. ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
  1744. if (ImGui::Button("200x200")) ImGui::SetWindowSize(ImVec2(200,200)); ImGui::SameLine();
  1745. if (ImGui::Button("500x500")) ImGui::SetWindowSize(ImVec2(500,500)); ImGui::SameLine();
  1746. if (ImGui::Button("800x200")) ImGui::SetWindowSize(ImVec2(800,200));
  1747. for (int i = 0; i < 10; i++)
  1748. ImGui::Text("Hello, sailor! Making this line long enough for the example.");
  1749. }
  1750. ImGui::End();
  1751. }
  1752. // Demonstrate creating a simple static window with no decoration.
  1753. static void ShowExampleAppFixedOverlay(bool* p_open)
  1754. {
  1755. ImGui::SetNextWindowPos(ImVec2(10,10));
  1756. if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings))
  1757. {
  1758. ImGui::End();
  1759. return;
  1760. }
  1761. ImGui::Text("Simple overlay\non the top-left side of the screen.");
  1762. ImGui::Separator();
  1763. ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
  1764. ImGui::End();
  1765. }
  1766. // Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
  1767. // Read 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." about ID.
  1768. static void ShowExampleAppManipulatingWindowTitle(bool*)
  1769. {
  1770. // By default, Windows are uniquely identified by their title.
  1771. // You can use the "##" and "###" markers to manipulate the display/ID.
  1772. // Using "##" to display same title but have unique identifier.
  1773. ImGui::SetNextWindowPos(ImVec2(100,100), ImGuiSetCond_FirstUseEver);
  1774. ImGui::Begin("Same title as another window##1");
  1775. ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
  1776. ImGui::End();
  1777. ImGui::SetNextWindowPos(ImVec2(100,200), ImGuiSetCond_FirstUseEver);
  1778. ImGui::Begin("Same title as another window##2");
  1779. ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
  1780. ImGui::End();
  1781. // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
  1782. char buf[128];
  1783. sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], rand());
  1784. ImGui::SetNextWindowPos(ImVec2(100,300), ImGuiSetCond_FirstUseEver);
  1785. ImGui::Begin(buf);
  1786. ImGui::Text("This window has a changing title.");
  1787. ImGui::End();
  1788. }
  1789. // Demonstrate using the low-level ImDrawList to draw custom shapes.
  1790. static void ShowExampleAppCustomRendering(bool* p_open)
  1791. {
  1792. ImGui::SetNextWindowSize(ImVec2(350,560), ImGuiSetCond_FirstUseEver);
  1793. if (!ImGui::Begin("Example: Custom rendering", p_open))
  1794. {
  1795. ImGui::End();
  1796. return;
  1797. }
  1798. // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
  1799. // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
  1800. // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
  1801. // In this example we are not using the maths operators!
  1802. ImDrawList* draw_list = ImGui::GetWindowDrawList();
  1803. // Primitives
  1804. ImGui::Text("Primitives");
  1805. static float sz = 36.0f;
  1806. static ImVec4 col = ImVec4(1.0f,1.0f,0.4f,1.0f);
  1807. ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
  1808. ImGui::ColorEdit3("Color", &col.x);
  1809. {
  1810. const ImVec2 p = ImGui::GetCursorScreenPos();
  1811. const ImU32 col32 = ImColor(col);
  1812. float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
  1813. for (int n = 0; n < 2; n++)
  1814. {
  1815. float thickness = (n == 0) ? 1.0f : 4.0f;
  1816. draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, thickness); x += sz+spacing;
  1817. draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ~0, thickness); x += sz+spacing;
  1818. draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ~0, thickness); x += sz+spacing;
  1819. draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, thickness); x += sz+spacing;
  1820. draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, thickness); x += sz+spacing;
  1821. draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, thickness); x += sz+spacing;
  1822. draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, thickness); x += spacing;
  1823. 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);
  1824. x = p.x + 4;
  1825. y += sz+spacing;
  1826. }
  1827. draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing;
  1828. draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;
  1829. draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;
  1830. draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing;
  1831. draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), ImColor(0,0,0), ImColor(255,0,0), ImColor(255,255,0), ImColor(0,255,0));
  1832. ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3));
  1833. }
  1834. ImGui::Separator();
  1835. {
  1836. static ImVector<ImVec2> points;
  1837. static bool adding_line = false;
  1838. ImGui::Text("Canvas example");
  1839. if (ImGui::Button("Clear")) points.clear();
  1840. if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
  1841. ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
  1842. // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
  1843. // However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
  1844. // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
  1845. ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
  1846. ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available
  1847. if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
  1848. if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
  1849. draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(50,50,50), ImColor(50,50,60), ImColor(60,60,70), ImColor(50,50,60));
  1850. draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(255,255,255));
  1851. bool adding_preview = false;
  1852. ImGui::InvisibleButton("canvas", canvas_size);
  1853. ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
  1854. if (adding_line)
  1855. {
  1856. adding_preview = true;
  1857. points.push_back(mouse_pos_in_canvas);
  1858. if (!ImGui::GetIO().MouseDown[0])
  1859. adding_line = adding_preview = false;
  1860. }
  1861. if (ImGui::IsItemHovered())
  1862. {
  1863. if (!adding_line && ImGui::IsMouseClicked(0))
  1864. {
  1865. points.push_back(mouse_pos_in_canvas);
  1866. adding_line = true;
  1867. }
  1868. if (ImGui::IsMouseClicked(1) && !points.empty())
  1869. {
  1870. adding_line = adding_preview = false;
  1871. points.pop_back();
  1872. points.pop_back();
  1873. }
  1874. }
  1875. draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y)); // clip lines within the canvas (if we resize it, etc.)
  1876. for (int i = 0; i < points.Size - 1; i += 2)
  1877. 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);
  1878. draw_list->PopClipRect();
  1879. if (adding_preview)
  1880. points.pop_back();
  1881. }
  1882. ImGui::End();
  1883. }
  1884. // Demonstrating creating a simple console window, with scrolling, filtering, completion and history.
  1885. // For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
  1886. struct ExampleAppConsole
  1887. {
  1888. char InputBuf[256];
  1889. ImVector<char*> Items;
  1890. bool ScrollToBottom;
  1891. ImVector<char*> History;
  1892. int HistoryPos; // -1: new line, 0..History.Size-1 browsing history.
  1893. ImVector<const char*> Commands;
  1894. ExampleAppConsole()
  1895. {
  1896. ClearLog();
  1897. memset(InputBuf, 0, sizeof(InputBuf));
  1898. HistoryPos = -1;
  1899. Commands.push_back("HELP");
  1900. Commands.push_back("HISTORY");
  1901. Commands.push_back("CLEAR");
  1902. Commands.push_back("CLASSIFY"); // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
  1903. AddLog("Welcome to ImGui!");
  1904. }
  1905. ~ExampleAppConsole()
  1906. {
  1907. ClearLog();
  1908. for (int i = 0; i < History.Size; i++)
  1909. free(History[i]);
  1910. }
  1911. // Portable helpers
  1912. static int Stricmp(const char* str1, const char* str2) { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }
  1913. static int Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; }
  1914. static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); }
  1915. void ClearLog()
  1916. {
  1917. for (int i = 0; i < Items.Size; i++)
  1918. free(Items[i]);
  1919. Items.clear();
  1920. ScrollToBottom = true;
  1921. }
  1922. void AddLog(const char* fmt, ...) IM_PRINTFARGS(2)
  1923. {
  1924. char buf[1024];
  1925. va_list args;
  1926. va_start(args, fmt);
  1927. vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
  1928. buf[IM_ARRAYSIZE(buf)-1] = 0;
  1929. va_end(args);
  1930. Items.push_back(Strdup(buf));
  1931. ScrollToBottom = true;
  1932. }
  1933. void Draw(const char* title, bool* p_open)
  1934. {
  1935. ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver);
  1936. if (!ImGui::Begin(title, p_open))
  1937. {
  1938. ImGui::End();
  1939. return;
  1940. }
  1941. 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.");
  1942. ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
  1943. // TODO: display items starting from the bottom
  1944. if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
  1945. if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine();
  1946. if (ImGui::SmallButton("Clear")) ClearLog(); ImGui::SameLine();
  1947. if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
  1948. //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
  1949. ImGui::Separator();
  1950. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
  1951. static ImGuiTextFilter filter;
  1952. filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
  1953. ImGui::PopStyleVar();
  1954. ImGui::Separator();
  1955. ImGui::BeginChild("ScrollingRegion", ImVec2(0,-ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar);
  1956. if (ImGui::BeginPopupContextWindow())
  1957. {
  1958. if (ImGui::Selectable("Clear")) ClearLog();
  1959. ImGui::EndPopup();
  1960. }
  1961. // 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());
  1962. // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
  1963. // 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.
  1964. // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
  1965. // ImGuiListClipper clipper(Items.Size);
  1966. // while (clipper.Step())
  1967. // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
  1968. // 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.
  1969. // 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,
  1970. // 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!
  1971. // 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.
  1972. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
  1973. for (int i = 0; i < Items.Size; i++)
  1974. {
  1975. const char* item = Items[i];
  1976. if (!filter.PassFilter(item))
  1977. continue;
  1978. ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f); // A better implementation may store a type per-item. For the sample let's just parse the text.
  1979. if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f);
  1980. else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f);
  1981. ImGui::PushStyleColor(ImGuiCol_Text, col);
  1982. ImGui::TextUnformatted(item);
  1983. ImGui::PopStyleColor();
  1984. }
  1985. if (ScrollToBottom)
  1986. ImGui::SetScrollHere();
  1987. ScrollToBottom = false;
  1988. ImGui::PopStyleVar();
  1989. ImGui::EndChild();
  1990. ImGui::Separator();
  1991. // Command-line
  1992. if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
  1993. {
  1994. char* input_end = InputBuf+strlen(InputBuf);
  1995. while (input_end > InputBuf && input_end[-1] == ' ') input_end--; *input_end = 0;
  1996. if (InputBuf[0])
  1997. ExecCommand(InputBuf);
  1998. strcpy(InputBuf, "");
  1999. }
  2000. // Demonstrate keeping auto focus on the input box
  2001. if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)))
  2002. ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
  2003. ImGui::End();
  2004. }
  2005. void ExecCommand(const char* command_line)
  2006. {
  2007. AddLog("# %s\n", command_line);
  2008. // 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.
  2009. HistoryPos = -1;
  2010. for (int i = History.Size-1; i >= 0; i--)
  2011. if (Stricmp(History[i], command_line) == 0)
  2012. {
  2013. free(History[i]);
  2014. History.erase(History.begin() + i);
  2015. break;
  2016. }
  2017. History.push_back(Strdup(command_line));
  2018. // Process command
  2019. if (Stricmp(command_line, "CLEAR") == 0)
  2020. {
  2021. ClearLog();
  2022. }
  2023. else if (Stricmp(command_line, "HELP") == 0)
  2024. {
  2025. AddLog("Commands:");
  2026. for (int i = 0; i < Commands.Size; i++)
  2027. AddLog("- %s", Commands[i]);
  2028. }
  2029. else if (Stricmp(command_line, "HISTORY") == 0)
  2030. {
  2031. for (int i = History.Size >= 10 ? History.Size - 10 : 0; i < History.Size; i++)
  2032. AddLog("%3d: %s\n", i, History[i]);
  2033. }
  2034. else
  2035. {
  2036. AddLog("Unknown command: '%s'\n", command_line);
  2037. }
  2038. }
  2039. static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
  2040. {
  2041. ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
  2042. return console->TextEditCallback(data);
  2043. }
  2044. int TextEditCallback(ImGuiTextEditCallbackData* data)
  2045. {
  2046. //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
  2047. switch (data->EventFlag)
  2048. {
  2049. case ImGuiInputTextFlags_CallbackCompletion:
  2050. {
  2051. // Example of TEXT COMPLETION
  2052. // Locate beginning of current word
  2053. const char* word_end = data->Buf + data->CursorPos;
  2054. const char* word_start = word_end;
  2055. while (word_start > data->Buf)
  2056. {
  2057. const char c = word_start[-1];
  2058. if (c == ' ' || c == '\t' || c == ',' || c == ';')
  2059. break;
  2060. word_start--;
  2061. }
  2062. // Build a list of candidates
  2063. ImVector<const char*> candidates;
  2064. for (int i = 0; i < Commands.Size; i++)
  2065. if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
  2066. candidates.push_back(Commands[i]);
  2067. if (candidates.Size == 0)
  2068. {
  2069. // No match
  2070. AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
  2071. }
  2072. else if (candidates.Size == 1)
  2073. {
  2074. // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
  2075. data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
  2076. data->InsertChars(data->CursorPos, candidates[0]);
  2077. data->InsertChars(data->CursorPos, " ");
  2078. }
  2079. else
  2080. {
  2081. // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
  2082. int match_len = (int)(word_end - word_start);
  2083. for (;;)
  2084. {
  2085. int c = 0;
  2086. bool all_candidates_matches = true;
  2087. for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
  2088. if (i == 0)
  2089. c = toupper(candidates[i][match_len]);
  2090. else if (c == 0 || c != toupper(candidates[i][match_len]))
  2091. all_candidates_matches = false;
  2092. if (!all_candidates_matches)
  2093. break;
  2094. match_len++;
  2095. }
  2096. if (match_len > 0)
  2097. {
  2098. data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
  2099. data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
  2100. }
  2101. // List matches
  2102. AddLog("Possible matches:\n");
  2103. for (int i = 0; i < candidates.Size; i++)
  2104. AddLog("- %s\n", candidates[i]);
  2105. }
  2106. break;
  2107. }
  2108. case ImGuiInputTextFlags_CallbackHistory:
  2109. {
  2110. // Example of HISTORY
  2111. const int prev_history_pos = HistoryPos;
  2112. if (data->EventKey == ImGuiKey_UpArrow)
  2113. {
  2114. if (HistoryPos == -1)
  2115. HistoryPos = History.Size - 1;
  2116. else if (HistoryPos > 0)
  2117. HistoryPos--;
  2118. }
  2119. else if (data->EventKey == ImGuiKey_DownArrow)
  2120. {
  2121. if (HistoryPos != -1)
  2122. if (++HistoryPos >= History.Size)
  2123. HistoryPos = -1;
  2124. }
  2125. // A better implementation would preserve the data on the current input line along with cursor position.
  2126. if (prev_history_pos != HistoryPos)
  2127. {
  2128. data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : "");
  2129. data->BufDirty = true;
  2130. }
  2131. }
  2132. }
  2133. return 0;
  2134. }
  2135. };
  2136. static void ShowExampleAppConsole(bool* p_open)
  2137. {
  2138. static ExampleAppConsole console;
  2139. console.Draw("Example: Console", p_open);
  2140. }
  2141. // Usage:
  2142. // static ExampleAppLog my_log;
  2143. // my_log.AddLog("Hello %d world\n", 123);
  2144. // my_log.Draw("title");
  2145. struct ExampleAppLog
  2146. {
  2147. ImGuiTextBuffer Buf;
  2148. ImGuiTextFilter Filter;
  2149. ImVector<int> LineOffsets; // Index to lines offset
  2150. bool ScrollToBottom;
  2151. void Clear() { Buf.clear(); LineOffsets.clear(); }
  2152. void AddLog(const char* fmt, ...) IM_PRINTFARGS(2)
  2153. {
  2154. int old_size = Buf.size();
  2155. va_list args;
  2156. va_start(args, fmt);
  2157. Buf.appendv(fmt, args);
  2158. va_end(args);
  2159. for (int new_size = Buf.size(); old_size < new_size; old_size++)
  2160. if (Buf[old_size] == '\n')
  2161. LineOffsets.push_back(old_size);
  2162. ScrollToBottom = true;
  2163. }
  2164. void Draw(const char* title, bool* p_open = NULL)
  2165. {
  2166. ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiSetCond_FirstUseEver);
  2167. ImGui::Begin(title, p_open);
  2168. if (ImGui::Button("Clear")) Clear();
  2169. ImGui::SameLine();
  2170. bool copy = ImGui::Button("Copy");
  2171. ImGui::SameLine();
  2172. Filter.Draw("Filter", -100.0f);
  2173. ImGui::Separator();
  2174. ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
  2175. if (copy) ImGui::LogToClipboard();
  2176. if (Filter.IsActive())
  2177. {
  2178. const char* buf_begin = Buf.begin();
  2179. const char* line = buf_begin;
  2180. for (int line_no = 0; line != NULL; line_no++)
  2181. {
  2182. const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
  2183. if (Filter.PassFilter(line, line_end))
  2184. ImGui::TextUnformatted(line, line_end);
  2185. line = line_end && line_end[1] ? line_end + 1 : NULL;
  2186. }
  2187. }
  2188. else
  2189. {
  2190. ImGui::TextUnformatted(Buf.begin());
  2191. }
  2192. if (ScrollToBottom)
  2193. ImGui::SetScrollHere(1.0f);
  2194. ScrollToBottom = false;
  2195. ImGui::EndChild();
  2196. ImGui::End();
  2197. }
  2198. };
  2199. // Demonstrate creating a simple log window with basic filtering.
  2200. static void ShowExampleAppLog(bool* p_open)
  2201. {
  2202. static ExampleAppLog log;
  2203. // Demo fill
  2204. static float last_time = -1.0f;
  2205. float time = ImGui::GetTime();
  2206. if (time - last_time >= 0.3f)
  2207. {
  2208. const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" };
  2209. log.AddLog("[%s] Hello, time is %.1f, rand() %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, (int)rand());
  2210. last_time = time;
  2211. }
  2212. log.Draw("Example: Log", p_open);
  2213. }
  2214. // Demonstrate create a window with multiple child windows.
  2215. static void ShowExampleAppLayout(bool* p_open)
  2216. {
  2217. ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiSetCond_FirstUseEver);
  2218. if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar))
  2219. {
  2220. if (ImGui::BeginMenuBar())
  2221. {
  2222. if (ImGui::BeginMenu("File"))
  2223. {
  2224. if (ImGui::MenuItem("Close")) *p_open = false;
  2225. ImGui::EndMenu();
  2226. }
  2227. ImGui::EndMenuBar();
  2228. }
  2229. // left
  2230. static int selected = 0;
  2231. ImGui::BeginChild("left pane", ImVec2(150, 0), true);
  2232. for (int i = 0; i < 100; i++)
  2233. {
  2234. char label[128];
  2235. sprintf(label, "MyObject %d", i);
  2236. if (ImGui::Selectable(label, selected == i))
  2237. selected = i;
  2238. }
  2239. ImGui::EndChild();
  2240. ImGui::SameLine();
  2241. // right
  2242. ImGui::BeginGroup();
  2243. ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us
  2244. ImGui::Text("MyObject: %d", selected);
  2245. ImGui::Separator();
  2246. ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
  2247. ImGui::EndChild();
  2248. ImGui::BeginChild("buttons");
  2249. if (ImGui::Button("Revert")) {}
  2250. ImGui::SameLine();
  2251. if (ImGui::Button("Save")) {}
  2252. ImGui::EndChild();
  2253. ImGui::EndGroup();
  2254. }
  2255. ImGui::End();
  2256. }
  2257. // Demonstrate create a simple property editor.
  2258. static void ShowExampleAppPropertyEditor(bool* p_open)
  2259. {
  2260. ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiSetCond_FirstUseEver);
  2261. if (!ImGui::Begin("Example: Property editor", p_open))
  2262. {
  2263. ImGui::End();
  2264. return;
  2265. }
  2266. 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.");
  2267. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
  2268. ImGui::Columns(2);
  2269. ImGui::Separator();
  2270. struct funcs
  2271. {
  2272. static void ShowDummyObject(const char* prefix, int uid)
  2273. {
  2274. ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
  2275. ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
  2276. bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
  2277. ImGui::NextColumn();
  2278. ImGui::AlignFirstTextHeightToWidgets();
  2279. ImGui::Text("my sailor is rich");
  2280. ImGui::NextColumn();
  2281. if (node_open)
  2282. {
  2283. static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
  2284. for (int i = 0; i < 8; i++)
  2285. {
  2286. ImGui::PushID(i); // Use field index as identifier.
  2287. if (i < 2)
  2288. {
  2289. ShowDummyObject("Child", 424242);
  2290. }
  2291. else
  2292. {
  2293. ImGui::AlignFirstTextHeightToWidgets();
  2294. // Here we use a Selectable (instead of Text) to highlight on hover
  2295. //ImGui::Text("Field_%d", i);
  2296. char label[32];
  2297. sprintf(label, "Field_%d", i);
  2298. ImGui::Bullet();
  2299. ImGui::Selectable(label);
  2300. ImGui::NextColumn();
  2301. ImGui::PushItemWidth(-1);
  2302. if (i >= 5)
  2303. ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
  2304. else
  2305. ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
  2306. ImGui::PopItemWidth();
  2307. ImGui::NextColumn();
  2308. }
  2309. ImGui::PopID();
  2310. }
  2311. ImGui::TreePop();
  2312. }
  2313. ImGui::PopID();
  2314. }
  2315. };
  2316. // Iterate dummy objects with dummy members (all the same data)
  2317. for (int obj_i = 0; obj_i < 3; obj_i++)
  2318. funcs::ShowDummyObject("Object", obj_i);
  2319. ImGui::Columns(1);
  2320. ImGui::Separator();
  2321. ImGui::PopStyleVar();
  2322. ImGui::End();
  2323. }
  2324. // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
  2325. static void ShowExampleAppLongText(bool* p_open)
  2326. {
  2327. ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiSetCond_FirstUseEver);
  2328. if (!ImGui::Begin("Example: Long text display", p_open))
  2329. {
  2330. ImGui::End();
  2331. return;
  2332. }
  2333. static int test_type = 0;
  2334. static ImGuiTextBuffer log;
  2335. static int lines = 0;
  2336. ImGui::Text("Printing unusually long amount of text.");
  2337. ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped\0");
  2338. ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
  2339. if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
  2340. ImGui::SameLine();
  2341. if (ImGui::Button("Add 1000 lines"))
  2342. {
  2343. for (int i = 0; i < 1000; i++)
  2344. log.append("%i The quick brown fox jumps over the lazy dog\n", lines+i);
  2345. lines += 1000;
  2346. }
  2347. ImGui::BeginChild("Log");
  2348. switch (test_type)
  2349. {
  2350. case 0:
  2351. // Single call to TextUnformatted() with a big buffer
  2352. ImGui::TextUnformatted(log.begin(), log.end());
  2353. break;
  2354. case 1:
  2355. {
  2356. // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
  2357. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
  2358. ImGuiListClipper clipper(lines);
  2359. while (clipper.Step())
  2360. for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
  2361. ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
  2362. ImGui::PopStyleVar();
  2363. break;
  2364. }
  2365. case 2:
  2366. // Multiple calls to Text(), not clipped (slow)
  2367. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
  2368. for (int i = 0; i < lines; i++)
  2369. ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
  2370. ImGui::PopStyleVar();
  2371. break;
  2372. }
  2373. ImGui::EndChild();
  2374. ImGui::End();
  2375. }
  2376. // End of Demo code
  2377. #else
  2378. void ImGui::ShowTestWindow(bool*) {}
  2379. void ImGui::ShowUserGuide() {}
  2380. void ImGui::ShowStyleEditor(ImGuiStyle*) {}
  2381. #endif