// Part of ImGui Bundle - MIT License - Copyright (c) 2022-2024 Pascal Thomet - https://github.com/pthom/imgui_bundle #include "hello_imgui/hello_imgui.h" #include "hello_imgui/icons_font_awesome_4.h" #include "imspinner/imspinner.h" #include "imgui_toggle/imgui_toggle.h" #include "imgui_toggle/imgui_toggle_presets.h" #include "imgui_toggle/imgui_toggle_palette.h" #include "imgui_toggle/imgui_toggle_renderer.h" #include "immapp/immapp.h" #include "portable_file_dialogs/portable_file_dialogs.h" #include "imgui-command-palette/imcmd_command_palette.h" #include "imgui-knobs/imgui-knobs.h" #include "ImGuiColorTextEdit/TextEditor.h" #ifdef IMGUI_BUNDLE_WITH_IMFILEDIALOG #include "ImFileDialog/ImFileDialog.h" #endif #include "imgui_md_wrapper.h" #include "ImCoolBar/ImCoolbar.h" #include "demo_utils/api_demos.h" #include #include void DemoKnobs() { ImGuiMd::RenderUnindented(R"( # Knobs [imgui-knobs](https://github.com/altschuler/imgui-knobs) provides knobs for ImGui. )"); static float knob_float_value = 0.f; static int knob_int_value = 0; std::vector> knob_types = { {ImGuiKnobVariant_Tick, "tick"}, {ImGuiKnobVariant_Dot, "dot"}, {ImGuiKnobVariant_Space, "space"}, {ImGuiKnobVariant_Stepped, "stepped"}, {ImGuiKnobVariant_Wiper, "wiper"}, {ImGuiKnobVariant_WiperDot, "wiper_dot"}, {ImGuiKnobVariant_WiperOnly, "wiper_only"}, }; auto show_float_knobs = [&knob_types](float knob_size) { std::string knob_size_str = std::to_string(knob_size); ImGui::PushID((knob_size_str + "_float").c_str()); for (const auto& [knob_type, knob_typename] : knob_types) { ImGuiKnobs::Knob( knob_typename.c_str(), &knob_float_value, /*v_min=*/ 0.0f, /*v_max=*/ 1.0f, /*speed=*/ 0, /*format=*/ "%.2f", /*variant=*/ knob_type, /*size=*/ knob_size, /*flags=*/ 0, /*steps=*/ 100 ); ImGui::SameLine(); } ImGui::NewLine(); ImGui::PopID(); }; auto show_int_knobs = [&knob_types](float knob_size) { std::string knob_size_str = std::to_string(knob_size); ImGui::PushID((knob_size_str + "_int").c_str()); for (const auto& [knob_type, knob_typename] : knob_types) { ImGuiKnobs::KnobInt( knob_typename.c_str(), &knob_int_value, /*v_min=*/ 0.0, /*v_max=*/ 15, /*speed=*/ 0, /*format=*/ "%02i", /*variant=*/ knob_type, /*size=*/ knob_size, /*flags=*/ 0, /*steps=*/ 10 ); ImGui::SameLine(); } ImGui::NewLine(); ImGui::PopID(); }; float knobsSizeSmall = ImmApp::EmSize() * 2.5; float knobsSizeBig = knobsSizeSmall * 1.3; ImGui::BeginGroup(); ImGui::Text("Some small knobs"); show_float_knobs(knobsSizeSmall); ImGui::EndGroup(); ImGui::SameLine(); ImGui::BeginGroup(); ImGui::Text("Some big knobs (int values)"); show_int_knobs(knobsSizeBig); ImGui::EndGroup(); } void DemoSpinner() { ImGuiMd::RenderUnindented(R"( # Spinners [imspinner](https://github.com/dalerank/imspinner) provides spinners for ImGui. )"); ImColor color(0.3f, 0.5f, 0.9f, 1.f); ImGui::Text("spinner_moving_dots"); ImGui::SameLine(); ImSpinner::SpinnerMovingDots("spinner_moving_dots", 20.0, 4.0, color, 20); ImGui::SameLine(); float radius = ImGui::GetFontSize() / 1.8f; ImGui::Text("spinner_arc_rotation"); ImGui::SameLine(); ImSpinner::SpinnerArcRotation("spinner_arc_rotation", radius, 4.0, color); ImGui::SameLine(); float radius1 = ImGui::GetFontSize() / 2.5f; ImGui::Text("spinner_ang_triple"); ImGui::SameLine(); ImSpinner::SpinnerAngTriple("spinner_ang_triple", radius1, radius1 * 1.5f, radius1 * 2.0f, 2.5f, color, color, color); } void DemoToggle() { static bool flag = true; ImGuiMd::RenderUnindented(R"( # Toggle Switch [imgui_toggle](https://github.com/cmdwtf/imgui_toggle) provides toggle switches for ImGui.""" )"); bool changed = false; changed |= ImGui::Toggle("Default Toggle", &flag); ImGui::SameLine(); changed |= ImGui::Toggle("Animated Toggle", &flag, ImGuiToggleFlags_Animated); ImGui::SameLine(); auto toggle_config = ImGuiTogglePresets::MaterialStyle(); toggle_config.AnimationDuration = 0.4f; changed |= ImGui::Toggle("Material Style (with slowed anim)", &flag, toggle_config); ImGui::SameLine(); changed |= ImGui::Toggle("iOS style", &flag, ImGuiTogglePresets::iOSStyle(0.2f)); ImGui::SameLine(); changed |= ImGui::Toggle( "iOS style (light)", &flag, ImGuiTogglePresets::iOSStyle(0.2f, true)); } void DemoPortableFileDialogs() { static std::string lastFileSelection; ImGui::PushID("pfd"); ImGuiMd::RenderUnindented(R"( # Portable File Dialogs [portable-file-dialogs](https://github.com/samhocevar/portable-file-dialogs) provides file dialogs as well as notifications and messages. They will use the native dialogs and notifications on each platform. )"); #ifdef __EMSCRIPTEN__ ImGuiMd::RenderUnindented(R"( *Note: On Emscripten/Web, only messages dialogs (with an Ok button and an icon) are supported. On Windows, Linux and MacOS, everything is supported.* )"); #endif ImGui::Text(" --- File dialogs ---"); auto logResult = [](std::string what) { lastFileSelection = what; }; auto logResultList = [](const std::vector& whats) { lastFileSelection = fplus::join(std::string("\n"), whats); }; static std::unique_ptr openFileDialog; if (ImGui::Button("Open File")) openFileDialog = std::make_unique("Select file"); if (openFileDialog.get() && openFileDialog->ready()) { logResultList(openFileDialog->result()); openFileDialog.reset(); } ImGui::SameLine(); static std::unique_ptr openFileMultiselect; if (ImGui::Button("Open File (multiselect)")) openFileMultiselect.reset(new pfd::open_file("Select file", "", {}, pfd::opt::multiselect)); if (openFileMultiselect.get() && openFileMultiselect->ready()) { logResultList(openFileMultiselect->result()); openFileMultiselect.reset(); } ImGui::SameLine(); static std::unique_ptr saveFileDialog; if (ImGui::Button("Save File")) saveFileDialog = std::make_unique("Save file"); if (saveFileDialog.get() && saveFileDialog->ready()) { logResult(saveFileDialog->result()); saveFileDialog.reset(); } ImGui::SameLine(); static std::unique_ptr selectFolderDialog; if (ImGui::Button("Select Folder")) selectFolderDialog = std::make_unique("Select folder"); if (selectFolderDialog.get() && selectFolderDialog->ready()) { logResult(selectFolderDialog->result()); selectFolderDialog.reset(); } if (lastFileSelection.size() > 0) ImGui::Text("%s", lastFileSelection.c_str()); ImGui::Text(" --- Notifications and messages ---"); static pfd::icon iconType = pfd::icon::info; static std::optional messageDialog; static pfd::choice messageChoiceType = pfd::choice::ok; // icon type ImGui::Text("Icon type"); ImGui::SameLine(); std::vector> iconTypes = { {pfd::icon::info, "info"}, {pfd::icon::warning, "warning"}, {pfd::icon::error, "error"}, }; for (const auto& [notification_icon, name]: iconTypes) { if (ImGui::RadioButton(name, iconType == notification_icon)) iconType = notification_icon; ImGui::SameLine(); } ImGui::NewLine(); if (ImGui::Button("Add Notif")) pfd::notify("Notification title", "This is an example notification", iconType); // messages ImGui::SameLine(); // 1. Display the message if (ImGui::Button("Add message")) messageDialog = pfd::message("Message title", "This is an example message", messageChoiceType, iconType); // 2. Handle the message result if (messageDialog.has_value() && messageDialog->ready()) { printf("msg ready\n"); // Get the result via messageDialog->result() messageDialog.reset(); } // Optional: Select the message type ImGui::SameLine(); std::vector> choiceTypes = { {pfd::choice::ok, "ok"}, {pfd::choice::yes_no, "yes_no"}, {pfd::choice::yes_no_cancel, "yes_no_cancel"}, {pfd::choice::retry_cancel, "retry_cancel"}, {pfd::choice::abort_retry_ignore, "abort_retry_ignore"}, }; for (const auto& [choice_type, name]: choiceTypes) { if (ImGui::RadioButton(name, messageChoiceType == choice_type)) messageChoiceType = choice_type; ImGui::SameLine(); } ImGui::NewLine(); ImGui::PopID(); } void DemoImFileDialog() { #ifdef IMGUI_BUNDLE_WITH_IMFILEDIALOG static std::string selectedFilename; ImGuiMd::RenderUnindented(R"( # ImFileDialog [ImFileDialog](https://github.com/pthom/ImFileDialog.git) provides file dialogs for ImGui. )"); ImGui::SameLine(); ImGui::Text(ICON_FA_EXCLAMATION_TRIANGLE); ImGui::SetItemTooltip( "It is advised to use Portable File Dialogs instead, which offer native dialogs on each platform, " "as well as notifications and messages.\n\n" "Known limitations of ImFileDialog:\n" " * Not adapted for High DPI resolution under windows\n" " * No support for multi-selection\n" " * Will not work under python with a pure python backend (requires to use `immapp.run()`)" ); if (ImGui::Button("Open file")) ifd::FileDialog::Instance().Open( "ShaderOpenDialog", "Open a shader", "Image file (*.png*.jpg*.jpeg*.bmp*.tga).png,.jpg,.jpeg,.bmp,.tga,.*", true ); ImGui::SameLine(); if (ImGui::Button("Open directory")) ifd::FileDialog::Instance().Open("DirectoryOpenDialog", "Open a directory", ""); ImGui::SameLine(); if (ImGui::Button("Save file")) ifd::FileDialog::Instance().Save("ShaderSaveDialog", "Save a shader", "*.sprj .sprj"); if (selectedFilename.size() > 0) ImGui::Text("Last file selection:\n%s", selectedFilename.c_str()); if (ifd::FileDialog::Instance().IsDone("ShaderOpenDialog")) { if (ifd::FileDialog::Instance().HasResult()) { // get_results: plural form - ShaderOpenDialog supports multi-selection auto results = ifd::FileDialog::Instance().GetResults(); selectedFilename = ""; for (auto path: results) selectedFilename += path.string() + "\n"; } ifd::FileDialog::Instance().Close(); } if (ifd::FileDialog::Instance().IsDone("DirectoryOpenDialog")) { if (ifd::FileDialog::Instance().HasResult()) selectedFilename = ifd::FileDialog::Instance().GetResult().string(); ifd::FileDialog::Instance().Close(); } if (ifd::FileDialog::Instance().IsDone("ShaderSaveDialog")) { if (ifd::FileDialog::Instance().HasResult()) selectedFilename = ifd::FileDialog::Instance().GetResult().string(); ifd::FileDialog::Instance().Close(); } #endif // #ifdef IMGUI_BUNDLE_WITH_IMFILEDIALOG } void DemoCommandPalette() { static bool wasInited = false; static bool showCommandPalette = false; static ImCmd::Context * commandPaletteContext = nullptr; static int counter = 0; auto initCommandPalette = []() { commandPaletteContext = ImCmd::CreateContext(); ImVec4 highlight_font_color(1.0f, 0.0f, 0.0f, 1.0f); ImCmd::SetStyleColor(ImCmdTextType_Highlight, ImGui::ColorConvertFloat4ToU32(highlight_font_color)); // Add theme command: a two steps command, with initial callback + SubsequentCallback { ImCmd::Command select_theme_cmd; select_theme_cmd.Name = "Select theme"; select_theme_cmd.InitialCallback = [&]() { ImCmd::Prompt(std::vector{ "Classic", "Dark", "Light", }); }; select_theme_cmd.SubsequentCallback = [&](int selected_option) { switch (selected_option) { case 0: ImGui::StyleColorsClassic(); break; case 1: ImGui::StyleColorsDark(); break; case 2: ImGui::StyleColorsLight(); break; default: break; } }; ImCmd::AddCommand(std::move(select_theme_cmd)); } // Simple command that increments a counter { ImCmd::Command inc_cmd; inc_cmd.Name = "increment counter"; inc_cmd.InitialCallback = [] { counter += 1; }; ImCmd::AddCommand(inc_cmd); } }; if (!wasInited) { initCommandPalette(); wasInited = true; } ImGuiMd::RenderUnindented(R"( # Command Palette [imgui-command-palette](https://github.com/hnOsmium0001/imgui-command-palette.git) provides a Sublime Text or VSCode style command palette in ImGui )"); auto& io = ImGui::GetIO(); if (io.KeyCtrl && io.KeyShift && ImGui::IsKeyPressed(ImGuiKey_P)) showCommandPalette = ! showCommandPalette; if (showCommandPalette) ImCmd::CommandPaletteWindow("CommandPalette", &showCommandPalette); ImGui::NewLine(); ImGui::Text("Press Ctrl+Shift+P to bring up the command palette"); ImGui::NewLine(); ImGui::Text("counter=%i", counter); } void DemoCoolBar() { auto ShowCoolBarButton = [](const std::string& label) -> bool { float w = ImGui::GetCoolBarItemWidth(); // Display transparent image and check if clicked HelloImGui::ImageFromAsset("images/bear_transparent.png", ImVec2(w, w)); bool clicked = ImGui::IsItemHovered() && ImGui::IsMouseClicked(0); // Optional: add a label on the image { ImVec2 topLeftCorner = ImGui::GetItemRectMin(); ImVec2 textPos(topLeftCorner.x + ImmApp::EmSize(1.f), topLeftCorner.y + ImmApp::EmSize(1.f)); ImGui::GetForegroundDrawList()->AddText(textPos, 0xFFFFFFFF, label.c_str()); } return clicked; }; std::vector buttonLabels {"A", "B", "C", "D", "E", "F"}; ImGuiMd::RenderUnindented(R"( # ImCoolBar: ImCoolBar provides a dock-like Cool bar for Dear ImGui )"); ImGui::ImCoolBarConfig coolBarConfig; coolBarConfig.anchor = ImVec2(0.5f, 0.07f); // position in the window (ratio of window size) if (ImGui::BeginCoolBar("##CoolBarMain", ImCoolBarFlags_Horizontal, coolBarConfig)) { for (const std::string& label: buttonLabels) { if (ImGui::CoolBarItem()) { if (ShowCoolBarButton(label)) printf("Clicked %s\n", label.c_str()); } } ImGui::EndCoolBar(); } ImGui::NewLine(); ImGui::NewLine(); } void demo_widgets() { DemoCoolBar(); DemoPortableFileDialogs(); ImGui::NewLine(); DemoImFileDialog(); ImGui::NewLine(); DemoKnobs(); DemoToggle(); ImGui::NewLine(); DemoSpinner(); DemoCommandPalette(); }