demo_imgui_bundle.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. # Part of ImGui Bundle - MIT License - Copyright (c) 2022-2026 Pascal Thomet - https://github.com/pthom/imgui_bundle
  2. import importlib.util
  3. import sys
  4. if importlib.util.find_spec("numpy") is None:
  5. print(
  6. "Dear ImGui Bundle Explorer requires numpy!\n"
  7. "Please install it with:\n"
  8. " pip install numpy\n"
  9. "or\n"
  10. " uv pip install numpy",
  11. file=sys.stderr,
  12. )
  13. sys.exit(1)
  14. from typing import List, Callable
  15. from types import ModuleType
  16. from dataclasses import dataclass, field
  17. from imgui_bundle import imgui, hello_imgui, immapp
  18. from imgui_bundle.immapp import static
  19. from imgui_bundle.demos_python import demo_text_edit
  20. from imgui_bundle.demos_python import demo_imgui_bundle_intro
  21. from imgui_bundle.demos_python import demo_imgui_show_demo_window
  22. from imgui_bundle.demos_python import demo_widgets
  23. from imgui_bundle.demos_python import demo_implot
  24. from imgui_bundle.demos_python import demo_imgui_md
  25. from imgui_bundle.demos_python import demo_immvision_launcher
  26. from imgui_bundle.demos_python import demo_imguizmo_launcher
  27. from imgui_bundle.demos_python import demo_tex_inspect_launcher
  28. from imgui_bundle.demos_python import demo_node_editor_launcher
  29. from imgui_bundle.demos_python import demo_immapp_launcher
  30. from imgui_bundle.demos_python import demo_nanovg_launcher
  31. from imgui_bundle.demos_python import demo_themes
  32. from imgui_bundle.demos_python import demo_logger
  33. from imgui_bundle.demos_python import demo_im_anim
  34. from imgui_bundle.demos_python import demo_utils
  35. _show_code_states: dict[str, bool] = {}
  36. def show_module_demo(demo_filename: str, demo_function: Callable[[], None], show_code: bool = False) -> None:
  37. if imgui.get_frame_count() < 2: # cf https://github.com/pthom/imgui_bundle/issues/293
  38. return
  39. if show_code:
  40. current = _show_code_states.get(demo_filename, False)
  41. _, current = imgui.checkbox("Show code##" + demo_filename, current)
  42. _show_code_states[demo_filename] = current
  43. if current:
  44. demo_utils.show_python_vs_cpp_file(demo_filename, 40)
  45. demo_function()
  46. @dataclass
  47. class DemoDetails:
  48. label: str
  49. demo_module: ModuleType
  50. show_code: bool = False
  51. @dataclass
  52. class DemoGroup:
  53. """A group of demos shown as collapsing headers inside a single tab."""
  54. label: str
  55. demos: List[DemoDetails] = field(default_factory=list)
  56. def _show_group_gui(group: DemoGroup) -> None:
  57. """Gui function for a grouped tab: each sub-demo is a collapsing header."""
  58. if imgui.get_frame_count() < 2:
  59. return
  60. for demo in group.demos:
  61. demo_module_name = demo.demo_module.__name__.split(".")[-1]
  62. if imgui.collapsing_header(demo.label):
  63. imgui.indent()
  64. show_module_demo(demo_module_name, demo.demo_module.demo_gui, demo.show_code)
  65. imgui.unindent()
  66. def make_params() -> tuple[hello_imgui.RunnerParams, immapp.AddOnsParams]:
  67. print(
  68. f"For information, demos sources are available in {demo_utils.api_demos.demos_python_folder()}"
  69. )
  70. ################################################################################################
  71. # Part 1: Define the runner params
  72. ################################################################################################
  73. # Hello ImGui params (they hold the settings as well as the Gui callbacks)
  74. runner_params = hello_imgui.RunnerParams()
  75. # Window size and title
  76. runner_params.app_window_params.window_title = (
  77. "Dear ImGui Bundle Explorer"
  78. )
  79. runner_params.app_window_params.window_geometry.size = (1400, 950)
  80. # Menu bar
  81. runner_params.imgui_window_params.show_menu_bar = True
  82. runner_params.imgui_window_params.show_status_bar = True
  83. runner_params.ini_clear_previous_settings = True
  84. ################################################################################################
  85. # Part 2: Define the application layout and windows
  86. ################################################################################################
  87. # First, tell HelloImGui that we want full screen dock space (this will create "MainDockSpace")
  88. runner_params.imgui_window_params.default_imgui_window_type = (
  89. hello_imgui.DefaultImGuiWindowType.provide_full_screen_dock_space
  90. )
  91. # In this demo, we also demonstrate multiple viewports.
  92. # you can drag windows outside out the main window in order to put their content into new native windows
  93. runner_params.imgui_window_params.enable_viewports = True
  94. #
  95. # Define our dockable windows : each window provide a Gui callback, and will be displayed
  96. # in a docking split.
  97. #
  98. dockable_windows: List[hello_imgui.DockableWindow] = []
  99. # --- Standalone tabs (no grouping) ---
  100. standalone_demos = [
  101. DemoDetails("Intro", demo_imgui_bundle_intro),
  102. DemoDetails("Dear ImGui", demo_imgui_show_demo_window),
  103. DemoDetails("Demo Apps", demo_immapp_launcher),
  104. ]
  105. for demo in standalone_demos:
  106. window = hello_imgui.DockableWindow()
  107. window.label = demo.label
  108. window.dock_space_name = "MainDockSpace"
  109. demo_module_name = demo.demo_module.__name__.split(".")[-1]
  110. def make_win_fn(mod_name: str, mod: ModuleType, sc: bool) -> Callable[[], None]:
  111. def win_fn() -> None:
  112. show_module_demo(mod_name, mod.demo_gui, sc)
  113. return win_fn
  114. window.gui_function = make_win_fn(demo_module_name, demo.demo_module, demo.show_code)
  115. dockable_windows.append(window)
  116. # --- Grouped tabs (sub-demos shown as collapsing headers) ---
  117. groups = [
  118. DemoGroup("Visualization", [
  119. DemoDetails("Plots with ImPlot and ImPlot3D", demo_implot),
  120. DemoDetails("ImmVision - Image analyzer", demo_immvision_launcher),
  121. DemoDetails("Tex Inspect - Texture Inspector", demo_tex_inspect_launcher),
  122. ]),
  123. DemoGroup("Widgets", [
  124. DemoDetails("Misc Widgets - Knobs, Toggles, ...", demo_widgets, show_code=True),
  125. DemoDetails("Logger - Log Window Widget", demo_logger, show_code=True),
  126. DemoDetails("ImGuizmo - Immediate Mode 3D Gizmo", demo_imguizmo_launcher),
  127. DemoDetails("Markdown - Rich Text Rendering", demo_imgui_md, show_code=True),
  128. DemoDetails("Text Editor - Code Editing Widget", demo_text_edit),
  129. ]),
  130. DemoGroup("Tools", [
  131. DemoDetails("Node Editor - Visual Node Graphs", demo_node_editor_launcher),
  132. DemoDetails("Themes - Style & Color Customization", demo_themes, show_code=True),
  133. DemoDetails("ImAnim - Animation Library", demo_im_anim),
  134. DemoDetails("NanoVG - 2D Vector Drawing", demo_nanovg_launcher),
  135. ]),
  136. ]
  137. for group in groups:
  138. window = hello_imgui.DockableWindow()
  139. window.label = group.label
  140. window.dock_space_name = "MainDockSpace"
  141. def make_group_fn(g: DemoGroup) -> Callable[[], None]:
  142. def win_fn() -> None:
  143. _show_group_gui(g)
  144. return win_fn
  145. window.gui_function = make_group_fn(group)
  146. dockable_windows.append(window)
  147. runner_params.docking_params.dockable_windows = dockable_windows
  148. # the main gui is only responsible to give focus to ImGui Bundle dockable window
  149. @static(nb_frames=0)
  150. def show_gui():
  151. if show_gui.nb_frames == 1:
  152. # Focus cannot be given at frame 0, since some additional windows will
  153. # be created after (and will steal the focus)
  154. runner_params.docking_params.focus_dockable_window("Dear ImGui Bundle")
  155. show_gui.nb_frames += 1
  156. def show_status_bar():
  157. from imgui_bundle import __version__, __build_number__
  158. imgui.set_next_item_width(imgui.get_content_region_avail().x / 10)
  159. _, imgui.get_style().font_scale_main = imgui.slider_float("Font scale", imgui.get_style().font_scale_main, 0.5, 5)
  160. imgui.same_line(spacing=hello_imgui.em_size(4))
  161. imgui.text_disabled(f"Dear ImGui Bundle Explorer - v{__version__} build {__build_number__}")
  162. runner_params.callbacks.show_status = show_status_bar
  163. runner_params.callbacks.show_gui = show_gui
  164. if "test_engine" in dir(imgui): # only enable test engine if available (i.e. if imgui bundle was compiled with it)
  165. runner_params.use_imgui_test_engine = True
  166. def setup_imgui_config() -> None:
  167. imgui.get_io().config_flags |= imgui.ConfigFlags_.nav_enable_keyboard.value
  168. runner_params.callbacks.setup_imgui_config = setup_imgui_config
  169. ################################################################################################
  170. # Part 3: Run the app
  171. ################################################################################################
  172. addons = immapp.AddOnsParams()
  173. addons.with_markdown = True
  174. addons.with_latex = True
  175. addons.with_node_editor = True
  176. addons.with_implot = True
  177. addons.with_implot3d = True
  178. addons.with_im_anim = True
  179. return runner_params, addons
  180. def main():
  181. from imgui_bundle import __version__, __build_number__, compilation_time
  182. print(f"Dear ImGui Bundle Explorer - v{__version__} build {__build_number__}, {compilation_time()}")
  183. runner_params, addons = make_params()
  184. immapp.run(runner_params=runner_params, add_ons_params=addons)
  185. if __name__ == "__main__":
  186. main()