PyImGui 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. pyimgui-0.1.0/.github/workflows/wheels.yml +76 -0
  2. pyimgui-0.1.0/.gitignore +1 -0
  3. pyimgui-0.1.0/CMakeLists.txt +177 -0
  4. pyimgui-0.1.0/LICENSE +21 -0
  5. pyimgui-0.1.0/PKG-INFO +311 -0
  6. pyimgui-0.1.0/README.md +291 -0
  7. pyimgui-0.1.0/THIRD_PARTY_LICENSES.txt +242 -0
  8. pyimgui-0.1.0/generate.py +834 -0
  9. pyimgui-0.1.0/pyproject.toml +64 -0
  10. pyimgui-0.1.0/src/bindings/imgui_bindings.cpp +6819 -0
  11. pyimgui-0.1.0/src/bindings/imgui_config.h +25 -0
  12. pyimgui-0.1.0/src/bindings/imgui_impl_dx12_bindings.cpp +163 -0
  13. pyimgui-0.1.0/src/bindings/imgui_impl_metal_bindings.mm +164 -0
  14. pyimgui-0.1.0/src/bindings/imgui_impl_opengl3_bindings.cpp +68 -0
  15. pyimgui-0.1.0/src/bindings/imgui_impl_sdl3_bindings.cpp +95 -0
  16. pyimgui-0.1.0/src/bindings/imgui_impl_sdlgpu3_bindings.cpp +91 -0
  17. pyimgui-0.1.0/src/bindings/imgui_impl_vulkan_bindings.cpp +367 -0
  18. pyimgui-0.1.0/src/bindings/imguizmo_bindings.cpp +388 -0
  19. pyimgui-0.1.0/src/bindings/implot_bindings.cpp +3864 -0
  20. pyimgui-0.1.0/src/bindings/module.cpp +57 -0
  21. pyimgui-0.1.0/src/bindings/native_casters.h +98 -0
  22. pyimgui-0.1.0/src/bindings/opaque_handle.h +65 -0
  23. pyimgui-0.1.0/src/bindings/sdl3_casters.h +109 -0
  24. pyimgui-0.1.0/src/bindings/style_colors.h +41 -0
  25. pyimgui-0.1.0/src/imgui/__init__.py +41 -0
  26. pyimgui-0.1.0/src/imgui/__init__.pyi +10140 -0
  27. pyimgui-0.1.0/src/imgui/app.py +219 -0
  28. pyimgui-0.1.0/src/imgui/app_dx12.py +673 -0
  29. pyimgui-0.1.0/src/imgui/app_metal4.py +251 -0
  30. pyimgui-0.1.0/src/imgui/app_opengl3.py +194 -0
  31. pyimgui-0.1.0/src/imgui/app_vulkan.py +805 -0
  32. pyimgui-0.1.0/src/imgui/imguizmo.pyi +501 -0
  33. pyimgui-0.1.0/src/imgui/impl_dx12.pyi +65 -0
  34. pyimgui-0.1.0/src/imgui/impl_metal.pyi +24 -0
  35. pyimgui-0.1.0/src/imgui/impl_metal4.pyi +34 -0
  36. pyimgui-0.1.0/src/imgui/impl_opengl3.pyi +81 -0
  37. pyimgui-0.1.0/src/imgui/impl_sdl3.pyi +100 -0
  38. pyimgui-0.1.0/src/imgui/impl_sdlgpu3.pyi +106 -0
  39. pyimgui-0.1.0/src/imgui/impl_vulkan.pyi +146 -0
  40. pyimgui-0.1.0/src/imgui/implot.pyi +2508 -0
  41. pyimgui-0.1.0/src/imgui/py.typed +0 -0
@@ -0,0 +1,76 @@
1
+ # Builds the wheels and the sdist, and uploads them to PyPI when a GitHub release is
2
+ # published. Its tag has to be the version in pyproject.toml, with or without a
3
+ # leading "v". Run it by hand (Actions > Wheels > Run workflow) to build and test
4
+ # the wheels without uploading them.
5
+ #
6
+ # The upload uses PyPI's trusted publishing, which the PyPI project has to be set
7
+ # up for: https://docs.pypi.org/trusted-publishers/ (workflow wheels.yml,
8
+ # environment pypi).
9
+ name: Wheels
10
+
11
+ on:
12
+ workflow_dispatch:
13
+ release:
14
+ types: [published]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ wheels:
21
+ name: Wheels on ${{ matrix.os }}
22
+ runs-on: ${{ matrix.os }}
23
+ strategy:
24
+ fail-fast: false
25
+ matrix:
26
+ # The runners' own architectures: x86-64 and ARM64 for Linux and Windows,
27
+ # ARM64 for macOS. The wheels need macOS 26 (see pyproject.toml), which no
28
+ # Intel runner has to test them on.
29
+ os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, windows-11-arm, macos-latest]
30
+ steps:
31
+ - uses: actions/checkout@v7
32
+ # The options are in pyproject.toml ([tool.cibuildwheel])
33
+ - uses: pypa/cibuildwheel@v4.2.1
34
+ env:
35
+ # The tests import pysdl3, which downloads SDL3 through GitHub's API
36
+ SDL_GITHUB_TOKEN: ${{ github.token }}
37
+ - uses: actions/upload-artifact@v7
38
+ with:
39
+ name: wheels-${{ matrix.os }}
40
+ path: wheelhouse/*.whl
41
+
42
+ sdist:
43
+ name: Source distribution
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@v7
47
+ - name: Check that the release tag is the version
48
+ if: github.event_name == 'release'
49
+ run: |
50
+ version=$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
51
+ if [ "${GITHUB_REF_NAME#v}" != "$version" ]; then
52
+ echo "::error::The release tag $GITHUB_REF_NAME is not the version in pyproject.toml, $version"
53
+ exit 1
54
+ fi
55
+ - run: pipx run build --sdist
56
+ - uses: actions/upload-artifact@v7
57
+ with:
58
+ name: sdist
59
+ path: dist/*.tar.gz
60
+
61
+ publish:
62
+ name: Upload to PyPI
63
+ if: github.event_name == 'release'
64
+ needs: [wheels, sdist]
65
+ runs-on: ubuntu-latest
66
+ environment:
67
+ name: pypi
68
+ url: https://pypi.org/p/PyImGui
69
+ permissions:
70
+ id-token: write
71
+ steps:
72
+ - uses: actions/download-artifact@v8
73
+ with:
74
+ path: dist
75
+ merge-multiple: true
76
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1 @@
1
+ build/
@@ -0,0 +1,177 @@
1
+ cmake_minimum_required(VERSION 3.24...4.4)
2
+ project(imgui_bindings LANGUAGES CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 17)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+
7
+ # The Dear ImGui release that the bindings in src/ were generated from. generate.py
8
+ # reads the tag from this line, so the two cannot drift apart: bump it, rerun
9
+ # generate.py, rebuild, and update its notices in THIRD_PARTY_LICENSES.txt.
10
+ set(IMGUI_GIT_TAG v1.93.0-docking)
11
+ # The same for ImPlot and ImGuizmo, as commits: their last releases predate their
12
+ # fixes for the ImDrawList changes of Dear ImGui 1.92.8
13
+ set(IMPLOT_GIT_TAG 851cdbdd60d1dfb64c23e987969694de0f547a6b)
14
+ set(IMGUIZMO_GIT_TAG 105e4fde45e4e74aae8973d98750820ef7aca7e2)
15
+
16
+ # The SDL3 release whose headers the backends are compiled against. SDL3 itself is
17
+ # not linked (see _imgui below), so the SDL3 loaded at runtime has to be this
18
+ # release or a newer one.
19
+ set(SDL3_VERSION 3.4.16)
20
+
21
+ # The Vulkan headers that the Vulkan backend is compiled against. Vulkan itself is
22
+ # not linked either: the backend looks its functions up at runtime (see below).
23
+ set(VULKAN_HEADERS_GIT_TAG vulkan-sdk-1.4.363.0)
24
+
25
+ include(FetchContent)
26
+ # The archives' files get the time of their extraction (DOWNLOAD_EXTRACT_TIMESTAMP
27
+ # FALSE), not their dates in the archive: those predate the objects of an earlier
28
+ # release in the kept build directory (see pyproject.toml), which would then pass
29
+ # for up to date after bumping a release below.
30
+ FetchContent_Declare(imgui
31
+ URL https://github.com/ocornut/imgui/archive/refs/tags/${IMGUI_GIT_TAG}.tar.gz
32
+ DOWNLOAD_EXTRACT_TIMESTAMP FALSE)
33
+ # Only the headers of SDL3 are used: SOURCE_SUBDIR names a directory without a
34
+ # CMakeLists.txt, so SDL3 is downloaded but not built
35
+ FetchContent_Declare(sdl3
36
+ URL https://github.com/libsdl-org/SDL/releases/download/release-${SDL3_VERSION}/SDL3-${SDL3_VERSION}.tar.gz
37
+ DOWNLOAD_EXTRACT_TIMESTAMP FALSE
38
+ SOURCE_SUBDIR include)
39
+ FetchContent_Declare(implot
40
+ URL https://github.com/epezent/implot/archive/${IMPLOT_GIT_TAG}.tar.gz
41
+ DOWNLOAD_EXTRACT_TIMESTAMP FALSE)
42
+ # ImGuizmo's own CMakeLists.txt builds all of its widgets: only ImGuizmo.cpp is compiled below
43
+ FetchContent_Declare(imguizmo
44
+ URL https://github.com/CedricGuillemet/ImGuizmo/archive/${IMGUIZMO_GIT_TAG}.tar.gz
45
+ DOWNLOAD_EXTRACT_TIMESTAMP FALSE
46
+ SOURCE_SUBDIR src)
47
+ # Only the headers, as for SDL3
48
+ FetchContent_Declare(vulkan_headers
49
+ URL https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/${VULKAN_HEADERS_GIT_TAG}.tar.gz
50
+ DOWNLOAD_EXTRACT_TIMESTAMP FALSE
51
+ SOURCE_SUBDIR include)
52
+ FetchContent_MakeAvailable(imgui sdl3 implot imguizmo vulkan_headers)
53
+
54
+ find_package(Python 3.12 REQUIRED COMPONENTS Interpreter Development.Module Development.SABIModule)
55
+ find_package(nanobind CONFIG REQUIRED)
56
+
57
+ # Dear ImGui, its C++ string helpers, the backends, ImPlot and ImGuizmo, compiled
58
+ # with the regular optimization flags (nanobind_add_module optimizes for size)
59
+ add_library(imgui STATIC
60
+ ${imgui_SOURCE_DIR}/imgui.cpp
61
+ ${imgui_SOURCE_DIR}/imgui_demo.cpp
62
+ ${imgui_SOURCE_DIR}/imgui_draw.cpp
63
+ ${imgui_SOURCE_DIR}/imgui_tables.cpp
64
+ ${imgui_SOURCE_DIR}/imgui_widgets.cpp
65
+ ${imgui_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp
66
+ ${imgui_SOURCE_DIR}/backends/imgui_impl_sdl3.cpp
67
+ ${imgui_SOURCE_DIR}/backends/imgui_impl_sdlgpu3.cpp
68
+ ${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp
69
+ ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp
70
+ ${implot_SOURCE_DIR}/implot.cpp
71
+ ${implot_SOURCE_DIR}/implot_items.cpp
72
+ ${implot_SOURCE_DIR}/implot_demo.cpp
73
+ ${imguizmo_SOURCE_DIR}/src/ImGuizmo.cpp)
74
+ target_include_directories(imgui PUBLIC
75
+ ${imgui_SOURCE_DIR}
76
+ ${imgui_SOURCE_DIR}/backends
77
+ ${imgui_SOURCE_DIR}/misc/cpp
78
+ ${implot_SOURCE_DIR}
79
+ ${imguizmo_SOURCE_DIR}/src)
80
+ target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG="imgui_config.h")
81
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
82
+ # IM_ASSERT throws (see imgui_config.h), which the few destructors that assert
83
+ # cannot pass on: an assertion that fails in one of them terminates instead
84
+ target_compile_options(imgui PUBLIC -Wno-exceptions)
85
+ endif()
86
+ target_include_directories(imgui PUBLIC src/bindings ${sdl3_SOURCE_DIR}/include)
87
+ set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE ON)
88
+ # OpenGL is not linked either: imgui_impl_opengl3_loader.h opens the system's
89
+ # OpenGL library at runtime (dlopen, or LoadLibrary on Windows) and looks up its
90
+ # functions there, in the GL context that is current
91
+ target_link_libraries(imgui PUBLIC ${CMAKE_DL_LIBS})
92
+ # Nor is Vulkan: without prototypes, the Vulkan backend calls the functions that
93
+ # ImGui_ImplVulkan_LoadFunctions() looks up, which the bindings do through the
94
+ # vkGetInstanceProcAddr of the Vulkan library that SDL3 loaded. Defined for the
95
+ # bindings as well, which have to see the same declarations.
96
+ target_include_directories(imgui PUBLIC ${vulkan_headers_SOURCE_DIR}/include)
97
+ target_compile_definitions(imgui PUBLIC IMGUI_IMPL_VULKAN_NO_PROTOTYPES)
98
+
99
+ # STABLE_ABI: the module uses the stable ABI only, so that one wheel (abi3, see
100
+ # pyproject.toml) serves every Python release from 3.12 on
101
+ nanobind_add_module(_imgui STABLE_ABI
102
+ src/bindings/module.cpp
103
+ src/bindings/imgui_bindings.cpp
104
+ src/bindings/imgui_impl_sdl3_bindings.cpp
105
+ src/bindings/imgui_impl_sdlgpu3_bindings.cpp
106
+ src/bindings/imgui_impl_opengl3_bindings.cpp
107
+ src/bindings/imgui_impl_vulkan_bindings.cpp
108
+ src/bindings/implot_bindings.cpp
109
+ src/bindings/imguizmo_bindings.cpp)
110
+ target_link_libraries(_imgui PRIVATE imgui)
111
+
112
+ # All of imgui_bindings.cpp's bindings sit in one function of some 6700 lines, which
113
+ # MSVC's optimizer takes superlinearly long to compile: around nine minutes, against
114
+ # the twelve seconds of the five other translation units together. Lowering the
115
+ # inlining level (/Ob1) does not help, so that one file is compiled unoptimized,
116
+ # which brings it down to some twenty seconds. The cost is a little overhead in the
117
+ # lambdas that forward to Dear ImGui, whose own code is optimized as usual in the
118
+ # imgui library above. /Od comes last and thus wins over the /O2 /Ob2 /Os of the
119
+ # release flags, which warns (D9025) but is exactly the intent.
120
+ if(MSVC)
121
+ set_source_files_properties(src/bindings/imgui_bindings.cpp
122
+ PROPERTIES COMPILE_OPTIONS "/Od")
123
+ endif()
124
+
125
+ # SDL3 is not linked: the module leaves its SDL functions unresolved, and they are
126
+ # looked up when it is loaded, in the SDL3 that pysdl3 loaded before (see
127
+ # src/imgui/__init__.py). The backends thus share pysdl3's SDL3, whose windows and
128
+ # events they are handed. Linux allows unresolved symbols in shared libraries as
129
+ # is, macOS has to be told; a Windows DLL cannot have any, so it links SDL3.dll,
130
+ # through the import library of the SDL3 release above. At runtime, Windows
131
+ # resolves SDL3.dll to the one pysdl3 has already loaded. The wheel must not bundle
132
+ # an SDL3.dll of its own (see the cibuildwheel options in pyproject.toml).
133
+ if(APPLE)
134
+ target_link_options(_imgui PRIVATE -Wl,-undefined,dynamic_lookup)
135
+ elseif(WIN32)
136
+ FetchContent_Declare(sdl3_devel
137
+ URL https://github.com/libsdl-org/SDL/releases/download/release-${SDL3_VERSION}/SDL3-devel-${SDL3_VERSION}-VC.zip
138
+ DOWNLOAD_EXTRACT_TIMESTAMP FALSE)
139
+ FetchContent_MakeAvailable(sdl3_devel)
140
+ find_package(SDL3 CONFIG REQUIRED COMPONENTS SDL3-shared PATHS ${sdl3_devel_SOURCE_DIR} NO_DEFAULT_PATH)
141
+ target_link_libraries(_imgui PRIVATE SDL3::SDL3-shared)
142
+ endif()
143
+
144
+ # The Direct3D 12 backend, on Windows. It loads d3d12.dll itself, and links DXGI and
145
+ # the shader compiler (d3dcompiler_47.dll), which are part of Windows.
146
+ if(WIN32)
147
+ target_sources(imgui PRIVATE ${imgui_SOURCE_DIR}/backends/imgui_impl_dx12.cpp)
148
+ target_link_libraries(imgui PUBLIC dxgi d3dcompiler)
149
+ target_sources(_imgui PRIVATE src/bindings/imgui_impl_dx12_bindings.cpp)
150
+ endif()
151
+
152
+ # The Metal backends, on macOS: Objective-C++, with ARC as Dear ImGui's examples
153
+ # build them. Both define Objective-C classes of the same names, which would clash
154
+ # when linked together (and with any other class of those names in the process,
155
+ # as the Objective-C runtime is global): each gets its own names.
156
+ if(APPLE)
157
+ enable_language(OBJCXX)
158
+ set(IMGUI_METAL_RENAMES
159
+ MetalBuffer MetalTexture MetalContext FramebufferDescriptor ImGuiViewportDataMetal shaderCode)
160
+ foreach(backend Metal Metal4)
161
+ string(TOLOWER ${backend} name)
162
+ set(renames)
163
+ foreach(symbol ${IMGUI_METAL_RENAMES})
164
+ list(APPEND renames "${symbol}=ImGui_Impl${backend}_${symbol}")
165
+ endforeach()
166
+ set_source_files_properties(${imgui_SOURCE_DIR}/backends/imgui_impl_${name}.mm PROPERTIES
167
+ COMPILE_DEFINITIONS "${renames}"
168
+ COMPILE_OPTIONS "-fobjc-arc;-fobjc-weak")
169
+ target_sources(imgui PRIVATE ${imgui_SOURCE_DIR}/backends/imgui_impl_${name}.mm)
170
+ endforeach()
171
+ target_link_libraries(imgui PUBLIC "-framework Metal" "-framework QuartzCore" "-framework Cocoa")
172
+ target_sources(_imgui PRIVATE src/bindings/imgui_impl_metal_bindings.mm)
173
+ set_source_files_properties(src/bindings/imgui_impl_metal_bindings.mm PROPERTIES
174
+ COMPILE_OPTIONS "-fobjc-arc")
175
+ endif()
176
+
177
+ install(TARGETS _imgui LIBRARY DESTINATION imgui)
pyimgui-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lukas Lipp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pyimgui-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,311 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyImGui
3
+ Version: 0.1.0
4
+ Summary: Python bindings for Dear ImGui, its SDL3, SDL_GPU, OpenGL 3, Vulkan, Direct3D 12 and Metal backends, ImPlot and ImGuizmo
5
+ Keywords: imgui,implot,imguizmo,sdl3,sdl_gpu,opengl,vulkan,direct3d12,metal,gui,plot,gizmo,bindings
6
+ Author-Email: Lukas Lipp <lukas.lipp@cg.tuwien.ac.at>
7
+ License-Expression: MIT AND BSD-3-Clause
8
+ License-File: LICENSE
9
+ License-File: THIRD_PARTY_LICENSES.txt
10
+ Project-URL: Homepage, https://github.com/fknfilewalker/PyImGui
11
+ Project-URL: Source, https://github.com/fknfilewalker/PyImGui
12
+ Project-URL: Issues, https://github.com/fknfilewalker/PyImGui/issues
13
+ Requires-Python: >=3.12
14
+ Provides-Extra: sdl3
15
+ Requires-Dist: pysdl3; extra == "sdl3"
16
+ Provides-Extra: metal
17
+ Requires-Dist: pysdl3; extra == "metal"
18
+ Requires-Dist: pyobjc-framework-Metal; sys_platform == "darwin" and extra == "metal"
19
+ Description-Content-Type: text/markdown
20
+
21
+ # imgui
22
+
23
+ Python bindings for [Dear ImGui](https://github.com/ocornut/imgui) (v1.93.0, docking branch), its
24
+ SDL3 platform backend, its SDL_GPU, OpenGL 3 and Vulkan renderer backends, on Windows its Direct3D 12
25
+ renderer backend, on macOS its Metal and Metal 4 renderer backends, [ImPlot](https://github.com/epezent/implot) and
26
+ [ImGuizmo](https://github.com/CedricGuillemet/ImGuizmo). The bindings are generated
27
+ with [litgen](https://pthom.github.io/litgen/) from the unmodified upstream headers and built with
28
+ nanobind. Windows, GPU devices and events come from
29
+ [pysdl3](https://github.com/Aermoss/PySDL3).
30
+
31
+ ```python
32
+ import imgui
33
+ from imgui import impl_sdl3, impl_sdlgpu3
34
+
35
+ imgui.create_context()
36
+ impl_sdl3.init_for_sdl_gpu(window) # pysdl3's window and GPU device
37
+ impl_sdlgpu3.init(impl_sdlgpu3.InitInfo(device=gpu_device, color_target_format=swapchain_format))
38
+ ...
39
+ impl_sdl3.process_event(event) # pysdl3's SDL_Event
40
+ impl_sdlgpu3.new_frame()
41
+ impl_sdl3.new_frame()
42
+ imgui.new_frame()
43
+ if imgui.begin("Hello")[0]:
44
+ changed, value = imgui.slider_float("Value", value, 0.0, 1.0)
45
+ imgui.end()
46
+ imgui.render()
47
+ draw_data = imgui.get_draw_data()
48
+ impl_sdlgpu3.prepare_draw_data(draw_data, command_buffer) # before the render pass
49
+ impl_sdlgpu3.render_draw_data(draw_data, command_buffer, render_pass)
50
+ ```
51
+
52
+ The full program is [src/imgui/app.py](src/imgui/app.py): `imgui.app.run()` sets all of this up
53
+ on Metal, Vulkan or Direct3D 12, and calls a function to build the GUI of every frame:
54
+
55
+ ```python
56
+ import imgui
57
+ from imgui import app
58
+
59
+ def gui():
60
+ imgui.text(f"Drawn with {app.context().backend.name}")
61
+
62
+ app.run(gui, window_title="Hello", window_size=(1280, 720), fps_idle=0,
63
+ backends=(app.Backend.vulkan, app.Backend.metal)) # by default, SDL's choice
64
+ ```
65
+
66
+ `backends` lists the SDL_GPU drivers in order of preference. `app.context()` holds the window
67
+ and the GPU device, and `app.context().app_shall_exit = True` closes the window.
68
+
69
+ ### OpenGL 3
70
+
71
+ `imgui.impl_opengl3` binds `imgui_impl_opengl3.h`, whose textures are GL texture names:
72
+ `imgui.image(imgui.ImTextureRef(texture), size)` takes the `GLuint`. The extension does not link
73
+ OpenGL: the backend opens the system's OpenGL library when `impl_opengl3.init()` runs, and calls it
74
+ in the GL context that is current. [src/imgui/app_opengl3.py](src/imgui/app_opengl3.py) is `run()` for
75
+ SDL3 and OpenGL, which creates a core profile context (3.2 by default, `gl_version=` for another)
76
+ and keeps it current while the GUI is built, so that any GL binding (PyOpenGL, moderngl...) can
77
+ draw into textures for it:
78
+
79
+ ```python
80
+ from imgui import app_opengl3
81
+
82
+ def gui():
83
+ imgui.image(imgui.ImTextureRef(texture), (512, 512)) # a GLuint of app_opengl3's context
84
+
85
+ app_opengl3.run(gui, window_title="Hello", post_init=create_textures)
86
+ ```
87
+
88
+ `app_opengl3.context()` holds the window and the `SDL_GLContext`.
89
+
90
+ ### Vulkan
91
+
92
+ `imgui.impl_vulkan` binds `imgui_impl_vulkan.h`. Its handles are ints (addresses), ctypes objects
93
+ or anything that `int()` converts (cffi's pointers, as the `vulkan` package has them), and
94
+ `impl_vulkan.InitInfo` and `impl_vulkan.PipelineInfo` take their fields as keyword arguments. Textures
95
+ are descriptor sets: `imgui.image(imgui.ImTextureRef(impl_vulkan.add_texture(view, layout)), size)`.
96
+ The extension does not link Vulkan: `impl_vulkan.init()` looks the backend's functions up through
97
+ the `vkGetInstanceProcAddr` of the Vulkan library that SDL3 loaded (for a window with
98
+ `SDL_WINDOW_VULKAN`), unless `impl_vulkan.load_functions()` was given another one.
99
+ [src/imgui/app_vulkan.py](src/imgui/app_vulkan.py) is `run()` for SDL3 and Vulkan 1.3, which it
100
+ calls through ctypes, and draws with dynamic rendering:
101
+
102
+ ```python
103
+ from imgui import app_vulkan, impl_vulkan
104
+
105
+ def gui():
106
+ context = app_vulkan.context() # the window, VkInstance, VkDevice, VkQueue, ...
107
+ context.keep_alive(texture) # until the GPU is done with this frame
108
+ imgui.image(imgui.ImTextureRef(descriptor_set), (512, 512)) # of impl_vulkan.add_texture()
109
+
110
+ app_vulkan.run(gui, window_title="Hello", device_extensions=["VK_KHR_external_memory_win32"])
111
+ ```
112
+
113
+ `context()` holds the handles as ints, and the address of `vkGetInstanceProcAddr` to load further
114
+ functions with. `device_extensions` and `instance_extensions` enable extensions beyond the swapchain's,
115
+ e.g. to share memory with another API, and `validation=True` enables the Khronos validation layer.
116
+
117
+ ### Direct3D 12 (Windows)
118
+
119
+ On Windows, `imgui.impl_dx12` binds `imgui_impl_dx12.h`. Its objects are ints (addresses) or ctypes
120
+ pointers (comtypes' as well), and descriptor handles are the ints of their `ptr`. The backend takes the
121
+ SRV descriptors of its textures from the application, through the Python functions
122
+ `srv_descriptor_alloc_fn` (returning a `(cpu_handle, gpu_handle)` pair) and `srv_descriptor_free_fn`
123
+ of `impl_dx12.InitInfo`. The texture of `imgui.image()` is the GPU handle of an SRV in the same
124
+ heap. [src/imgui/app_dx12.py](src/imgui/app_dx12.py) is `run()` for SDL3 and Direct3D 12, which
125
+ it calls through ctypes, and hands out the descriptors of its heap:
126
+
127
+ ```python
128
+ from imgui import app_dx12
129
+
130
+ srv = {}
131
+
132
+ def post_init():
133
+ srv["cpu"], srv["gpu"] = app_dx12.context().allocate_srv_descriptor()
134
+ ... # ID3D12Device::CreateShaderResourceView(texture, ..., srv["cpu"])
135
+
136
+ def gui():
137
+ imgui.image(imgui.ImTextureRef(srv["gpu"]), (512, 512))
138
+
139
+ app_dx12.run(gui, window_title="Hello", post_init=post_init, device=device) # by default, its own device
140
+ ```
141
+
142
+ `context()` holds the window, the `ID3D12Device`, the `ID3D12CommandQueue` and the descriptor
143
+ heap, as ints, and `validation=True` enables the debug layer, whose messages are printed.
144
+
145
+ ### Metal and Metal 4 (macOS)
146
+
147
+ On macOS, `imgui.impl_metal` and `imgui.impl_metal4` bind `imgui_impl_metal.h` and
148
+ `imgui_impl_metal4.h`. Their Metal objects are
149
+ [PyObjC](https://pyobjc.readthedocs.io)'s (the `metal` extra installs `pyobjc-framework-Metal`),
150
+ ctypes pointers or addresses; `texture_id(texture)` gives the `ImTextureID` of any `MTLTexture`.
151
+ [src/imgui/app_metal4.py](src/imgui/app_metal4.py) is `run()` for SDL3 and Metal 4, which also takes
152
+ the `MTLDevice` to draw with:
153
+
154
+ ```python
155
+ from imgui import app_metal4, impl_metal4
156
+
157
+ def gui():
158
+ context = app_metal4.context() # the window, MTLDevice, MTL4CommandQueue, ...
159
+ context.keep_alive(texture) # until the GPU is done with this frame
160
+ imgui.image(imgui.ImTextureRef(impl_metal4.texture_id(texture)), (512, 512))
161
+
162
+ app_metal4.run(gui, window_title="Hello", device=device) # by default, the system's device
163
+ ```
164
+
165
+ The GUI can so show textures that view the memory of another library on the same device, e.g. a
166
+ GPU array's buffer (`MTLBuffer.newTextureWithDescriptor:offset:bytesPerRow:`). Metal 4 queues do not
167
+ track hazards: the queue has to wait for the other library's work (`context().command_queue
168
+ .waitForEvent_value_()`), the memory has to stay alive while frames draw it (`keep_alive()`), and the
169
+ buffers behind views belong in `context().residency_set`. The backend adds every texture that it draws
170
+ to a residency set of its own, which retains it: `impl_metal4.forget_texture()` removes one that is
171
+ no longer drawn.
172
+
173
+ ## Installing
174
+
175
+ PyPI has wheels for Python 3.12+ on Windows and Linux (glibc 2.34+), on x86-64 and ARM64, and on macOS 26+
176
+ on Apple silicon. Running needs pysdl3, which the `sdl3` extra installs (its SDL3 is what needs macOS 26).
177
+
178
+ ```sh
179
+ pip install "PyImGui[sdl3]" # or: uv pip install "PyImGui[sdl3]"
180
+ ```
181
+
182
+ Building from source needs a C++17 compiler and CMake. CMake downloads Dear ImGui, ImPlot, ImGuizmo
183
+ and the headers of SDL3 and Vulkan, which are not built or linked; on Windows, it also downloads the SDL3 import
184
+ library to link against.
185
+
186
+ ```sh
187
+ pip install ".[sdl3]" # in the repository's root
188
+ ```
189
+
190
+ On macOS, the Metal backends need PyObjC's Metal bindings, which the `metal` extra adds:
191
+ `pip install ".[metal]"`.
192
+
193
+ ## The Python API
194
+
195
+ The module follows these conventions:
196
+
197
+ - `ImGui::BeginTable()` is `imgui.begin_table()`, `ImGuiWindowFlags_NoResize` is
198
+ `imgui.WindowFlags_.no_resize`, `ImGuiIO` is `imgui.IO`.
199
+ - Functions that modify their pointer arguments return the new values instead:
200
+ `changed, v = imgui.checkbox("On", v)`, `visible, p_open = imgui.begin("Window", p_open)`.
201
+ - Tuples and lists work wherever an `ImVec2` or `ImVec4` is expected, and `ImVec2`/`ImVec4`
202
+ support arithmetic, indexing and unpacking.
203
+ - Strings are Python strings, `imgui.input_text("Name", name)` included.
204
+ - `io.ini_filename` sets or (with `None`) disables the settings file.
205
+ - The colors of a style are indexed by its `Col_` enum: `style.colors[imgui.Col_.text] = (1, 1, 1, 1)`.
206
+ The same goes for `implot.Style` and `imguizmo.Style`.
207
+ - The backends are the submodules `imgui.impl_sdl3`, `imgui.impl_sdlgpu3`, `imgui.impl_opengl3`,
208
+ `imgui.impl_vulkan` and, on Windows, `imgui.impl_dx12`:
209
+ `ImGui_ImplSDL3_ProcessEvent()` is `imgui.impl_sdl3.process_event()`. ImPlot and ImGuizmo are
210
+ `imgui.implot` and `imgui.imguizmo` (see below).
211
+
212
+ SDL objects are passed as pysdl3 creates them: its pointers (`SDL_Window*`, `SDL_GPUDevice*`,
213
+ ...), its `SDL_Event`, `ctypes.byref()` of one, or plain addresses. SDL's enums are ints, as
214
+ in pysdl3.
215
+
216
+ Textures are passed to `imgui.image()` and similar functions as `imgui.ImTextureRef(id)`. The `id`
217
+ is the address of the `SDL_GPUTexture` (`ctypes.cast(texture, ctypes.c_void_p).value`).
218
+
219
+ Dear ImGui's assertions raise a `RuntimeError`. This covers the API misuse it checks for, such as a
220
+ missing `end()`. To recover from those errors in the running app instead, set
221
+ `io.config_error_recovery_enable_assert = False`.
222
+
223
+ The extension does not link SDL3 (except on Windows). Its SDL functions are looked up when
224
+ `import imgui` loads it, in the SDL3 library that pysdl3 ships, which `import imgui` imports and
225
+ exposes first. The backends and pysdl3 thus share one SDL3, so the windows and events that pysdl3
226
+ creates are the backends' own. That library has to be SDL 3.4.16 or newer, the release whose headers
227
+ the extension is compiled against (`SDL3_VERSION` in [CMakeLists.txt](CMakeLists.txt)).
228
+
229
+ Not bound: C callbacks (`InputText` and size-constraint callbacks, `ImDrawList.add_callback`,
230
+ ImPlot's getters, formatters and transforms), drag-and-drop payloads, the memory allocators, the
231
+ `va_list` variants of the text functions, the manual gamepad mode of the SDL3 backend, the per-point
232
+ color and size arrays of `implot.Spec`, the row and column ratios of `implot.begin_subplots()`,
233
+ ImGuizmo's other widgets (ImSequencer, ImCurveEdit...), and the internal headers.
234
+
235
+ ## ImPlot and ImGuizmo
236
+
237
+ ```python
238
+ import math
239
+ import numpy as np
240
+ import imgui
241
+ from imgui import app, imguizmo, implot
242
+
243
+ xs = np.linspace(0, 10, 200)
244
+ model = np.eye(4, dtype=np.float32) # modified in place by the gizmo, hence float32
245
+ view = np.eye(4, dtype=np.float32)
246
+ view[2, 3] = -5 # camera 5 units back, looking down -z
247
+ f, near, far = 1 / math.tan(math.radians(22.5)), 0.1, 100.0
248
+ projection = np.array([[f / 16 * 9, 0, 0, 0], [0, f, 0, 0], # OpenGL's perspective, 16:9
249
+ [0, 0, (far + near) / (near - far), 2 * far * near / (near - far)],
250
+ [0, 0, -1, 0]])
251
+
252
+ def gui():
253
+ imguizmo.begin_frame()
254
+ imgui.begin("Plot")
255
+ if implot.begin_plot("Waves"):
256
+ implot.plot_line("sin", xs, np.sin(xs), implot.Spec(line_weight=2, marker=implot.Marker_.circle))
257
+ implot.plot_bars("bars", np.arange(5))
258
+ implot.end_plot()
259
+ imgui.end()
260
+ size = imgui.get_io().display_size
261
+ imguizmo.set_rect(0, 0, size.x, size.y)
262
+ imguizmo.manipulate(view, projection, imguizmo.OPERATION.translate | imguizmo.OPERATION.rotate,
263
+ imguizmo.MODE.world, model)
264
+
265
+ app.run(gui, window_size=(1280, 720))
266
+ ```
267
+
268
+ - ImPlot needs a context of its own, which `app.run()` creates. Elsewhere, call
269
+ `implot.create_context()` after `imgui.create_context()`.
270
+ - The plotting functions take numpy arrays (or any array with DLPack or the buffer protocol) of any
271
+ integer or floating-point type. The arrays of one call share a type and are 1D and contiguous,
272
+ except for `plot_heatmap()` and `plot_bar_groups()`, which take a 2D array. `implot.Spec` holds
273
+ the style of an item, and takes its fields as keyword arguments. `ImPlotPoint` is
274
+ `implot.Point`, for which tuples work as well.
275
+ - `imguizmo.begin_frame()` starts each frame, after `imgui.new_frame()`. Matrices are 4x4 arrays
276
+ indexed `[row, column]`, whatever their memory order: the translation of a model matrix is
277
+ `matrix[:3, 3]`, and vectors are multiplied from the right, as in OpenGL. The functions that
278
+ modify a matrix (`manipulate()`, `view_manipulate()`, `recompose_matrix_from_components()`) write
279
+ it back into the array, which must be float32. The others take any numeric type.
280
+
281
+ ## Layout and regenerating the bindings
282
+
283
+ - `CMakeLists.txt` pins the Dear ImGui release (`IMGUI_GIT_TAG`), the ImPlot and ImGuizmo commits
284
+ (`IMPLOT_GIT_TAG`, `IMGUIZMO_GIT_TAG`) and the Vulkan headers (`VULKAN_HEADERS_GIT_TAG`), and
285
+ builds the single extension `imgui._imgui`, which holds them, the backends and all the bindings. They have to live in one extension because Dear
286
+ ImGui keeps its state in globals.
287
+ - `.github/workflows/wheels.yml` builds the wheels with cibuildwheel (options in `pyproject.toml`),
288
+ and uploads them to PyPI when a GitHub release is published. Bump `version` in `pyproject.toml`
289
+ first: the release tag has to match it (`v0.2.0` for `0.2.0`).
290
+ - `generate.py` holds the litgen options, and writes the code between the litgen markers of
291
+ `src/bindings/*.cpp` and `src/imgui/*.pyi`. The code outside those markers is written by hand:
292
+ the module definition, the Metal backends' bindings (`imgui_impl_metal_bindings.mm`, whose
293
+ Objective-C headers litgen cannot parse), the Vulkan and Direct3D 12 backends' bindings
294
+ (`imgui_impl_vulkan_bindings.cpp`, `imgui_impl_dx12_bindings.cpp`, whose structs hold native
295
+ structs and C callbacks), the SDL casters in `sdl3_casters.h`, the casters of native GPU handles
296
+ in `native_casters.h`, the opaque `Context` handles, the
297
+ `IM_ASSERT` of `imgui_config.h`, the ImGuizmo functions that take matrices, and the ImPlot
298
+ functions that take 2D arrays or labels.
299
+
300
+ The generated code is checked in, so building does not need litgen. After changing the options or
301
+ a pinned release, regenerate it with:
302
+
303
+ ```sh
304
+ uv run generate.py # or: pip install litgen && python generate.py
305
+ ```
306
+
307
+ ## License
308
+
309
+ MIT ([LICENSE](LICENSE)); the code that litgen generates is not subject to litgen's GPL. The wheels
310
+ also contain Dear ImGui with its fonts, ImPlot, ImGuizmo and nanobind, whose licenses are in
311
+ [THIRD_PARTY_LICENSES.txt](THIRD_PARTY_LICENSES.txt).