0
# Drawing and Graphics
1
2
Low-level drawing capabilities for custom graphics, shapes, text rendering, and advanced visual effects using draw lists. The drawing system provides direct access to ImGui's rendering pipeline for creating custom visualizations and graphics.
3
4
## Capabilities
5
6
### Draw List Access
7
8
Functions to obtain draw list objects for different rendering layers.
9
10
```python { .api }
11
def get_window_draw_list():
12
"""Get draw list for current window (most common)."""
13
14
def get_background_draw_list():
15
"""Get background draw list (renders behind all windows)."""
16
17
def get_foreground_draw_list():
18
"""Get foreground draw list (renders in front of all windows)."""
19
```
20
21
### Clipping and Scissoring
22
23
Functions to control rendering regions and clipping rectangles.
24
25
```python { .api }
26
def push_clip_rect(clip_rect_min_x: float, clip_rect_min_y: float, clip_rect_max_x: float, clip_rect_max_y: float, intersect_with_current_clip_rect: bool) -> None:
27
"""Push clip rectangle onto stack."""
28
29
def pop_clip_rect() -> None:
30
"""Pop clip rectangle from stack."""
31
```
32
33
### Item Rectangle Queries
34
35
Functions to query bounding rectangles of the last drawn item.
36
37
```python { .api }
38
def get_item_rect_min() -> tuple[float, float]:
39
"""Get minimum point of last item's bounding rectangle."""
40
41
def get_item_rect_max() -> tuple[float, float]:
42
"""Get maximum point of last item's bounding rectangle."""
43
44
def get_item_rect_size() -> tuple[float, float]:
45
"""Get size of last item's bounding rectangle."""
46
47
def set_item_allow_overlap() -> None:
48
"""Allow last item to be overlapped by subsequent items."""
49
50
def is_rect_visible(width: float, height: float) -> bool:
51
"""Test if rectangle of given size is visible."""
52
```
53
54
### Draw List Methods
55
56
Methods available on draw list objects for drawing primitives.
57
58
```python { .api }
59
class _DrawList:
60
"""ImGui draw list for custom rendering."""
61
62
def add_line(self, p1: tuple[float, float], p2: tuple[float, float], color: int, thickness: float = 1.0) -> None:
63
"""Draw a line between two points."""
64
65
def add_rect(self, p_min: tuple[float, float], p_max: tuple[float, float], color: int, rounding: float = 0.0, flags: int = 0, thickness: float = 1.0) -> None:
66
"""Draw a rectangle outline."""
67
68
def add_rect_filled(self, p_min: tuple[float, float], p_max: tuple[float, float], color: int, rounding: float = 0.0, flags: int = 0) -> None:
69
"""Draw a filled rectangle."""
70
71
def add_quad(self, p1: tuple[float, float], p2: tuple[float, float], p3: tuple[float, float], p4: tuple[float, float], color: int, thickness: float = 1.0) -> None:
72
"""Draw a quadrilateral outline."""
73
74
def add_quad_filled(self, p1: tuple[float, float], p2: tuple[float, float], p3: tuple[float, float], p4: tuple[float, float], color: int) -> None:
75
"""Draw a filled quadrilateral."""
76
77
def add_triangle(self, p1: tuple[float, float], p2: tuple[float, float], p3: tuple[float, float], color: int, thickness: float = 1.0) -> None:
78
"""Draw a triangle outline."""
79
80
def add_triangle_filled(self, p1: tuple[float, float], p2: tuple[float, float], p3: tuple[float, float], color: int) -> None:
81
"""Draw a filled triangle."""
82
83
def add_circle(self, center: tuple[float, float], radius: float, color: int, num_segments: int = 0, thickness: float = 1.0) -> None:
84
"""Draw a circle outline."""
85
86
def add_circle_filled(self, center: tuple[float, float], radius: float, color: int, num_segments: int = 0) -> None:
87
"""Draw a filled circle."""
88
89
def add_ngon(self, center: tuple[float, float], radius: float, color: int, num_segments: int, thickness: float = 1.0) -> None:
90
"""Draw a regular N-gon outline."""
91
92
def add_ngon_filled(self, center: tuple[float, float], radius: float, color: int, num_segments: int) -> None:
93
"""Draw a filled regular N-gon."""
94
95
def add_text(self, pos: tuple[float, float], color: int, text: str) -> None:
96
"""Draw text at specified position."""
97
98
def add_polyline(self, points: list[tuple[float, float]], color: int, flags: int, thickness: float) -> None:
99
"""Draw a polyline (connected line segments)."""
100
101
def add_convex_poly_filled(self, points: list[tuple[float, float]], color: int) -> None:
102
"""Draw a filled convex polygon."""
103
104
def add_bezier_cubic(self, p1: tuple[float, float], p2: tuple[float, float], p3: tuple[float, float], p4: tuple[float, float], color: int, thickness: float, num_segments: int = 0) -> None:
105
"""Draw a cubic Bezier curve."""
106
107
def add_bezier_quadratic(self, p1: tuple[float, float], p2: tuple[float, float], p3: tuple[float, float], color: int, thickness: float, num_segments: int = 0) -> None:
108
"""Draw a quadratic Bezier curve."""
109
110
def add_image(self, texture_id: int, p_min: tuple[float, float], p_max: tuple[float, float], uv_min: tuple[float, float] = (0, 0), uv_max: tuple[float, float] = (1, 1), color: int = 0xFFFFFFFF) -> None:
111
"""Draw a textured rectangle."""
112
113
def add_image_quad(self, texture_id: int, p1: tuple[float, float], p2: tuple[float, float], p3: tuple[float, float], p4: tuple[float, float], uv1: tuple[float, float] = (0, 0), uv2: tuple[float, float] = (1, 0), uv3: tuple[float, float] = (1, 1), uv4: tuple[float, float] = (0, 1), color: int = 0xFFFFFFFF) -> None:
114
"""Draw a textured quadrilateral."""
115
116
def add_image_rounded(self, texture_id: int, p_min: tuple[float, float], p_max: tuple[float, float], uv_min: tuple[float, float], uv_max: tuple[float, float], color: int, rounding: float, flags: int = 0) -> None:
117
"""Draw a textured rectangle with rounded corners."""
118
119
def path_clear(self) -> None:
120
"""Clear the current path."""
121
122
def path_line_to(self, pos: tuple[float, float]) -> None:
123
"""Add a point to the current path."""
124
125
def path_line_to_merge_duplicate(self, pos: tuple[float, float]) -> None:
126
"""Add a point to path, merging if duplicate."""
127
128
def path_fill_convex(self, color: int) -> None:
129
"""Fill the current path as a convex shape."""
130
131
def path_stroke(self, color: int, flags: int, thickness: float) -> None:
132
"""Stroke the current path with specified color and thickness."""
133
```
134
135
### Color Utility Functions
136
137
Functions for color format conversion and manipulation.
138
139
```python { .api }
140
def color_convert_u32_to_float4(color_u32: int) -> tuple[float, float, float, float]:
141
"""Convert U32 color to float4 RGBA."""
142
143
def color_convert_float4_to_u32(r: float, g: float, b: float, a: float) -> int:
144
"""Convert float4 RGBA to U32 color."""
145
146
def color_convert_rgb_to_hsv(r: float, g: float, b: float) -> tuple[float, float, float]:
147
"""Convert RGB to HSV color space."""
148
149
def color_convert_hsv_to_rgb(h: float, s: float, v: float) -> tuple[float, float, float]:
150
"""Convert HSV to RGB color space."""
151
152
def get_color_u32_idx(idx: int, alpha_mul: float = 1.0) -> int:
153
"""Get U32 color by style color index."""
154
155
def get_color_u32_rgba(r: float, g: float, b: float, a: float) -> int:
156
"""Get U32 color from RGBA float values."""
157
158
def get_color_u32(color: tuple[float, float, float, float]) -> int:
159
"""Get U32 color from RGBA tuple."""
160
```
161
162
### Drawing Flags
163
164
Constants for controlling drawing behavior.
165
166
```python { .api }
167
# Basic drawing flags
168
DRAW_NONE: int
169
DRAW_CLOSED: int # Connect last and first points
170
171
# Corner rounding flags
172
DRAW_ROUND_CORNERS_TOP_LEFT: int
173
DRAW_ROUND_CORNERS_TOP_RIGHT: int
174
DRAW_ROUND_CORNERS_BOTTOM_LEFT: int
175
DRAW_ROUND_CORNERS_BOTTOM_RIGHT: int
176
DRAW_ROUND_CORNERS_NONE: int # Disable rounding on all corners
177
DRAW_ROUND_CORNERS_TOP: int # Top left + top right
178
DRAW_ROUND_CORNERS_BOTTOM: int # Bottom left + bottom right
179
DRAW_ROUND_CORNERS_LEFT: int # Top left + bottom left
180
DRAW_ROUND_CORNERS_RIGHT: int # Top right + bottom right
181
DRAW_ROUND_CORNERS_ALL: int # All corners
182
183
# Draw list flags
184
DRAW_LIST_NONE: int
185
DRAW_LIST_ANTI_ALIASED_LINES: int
186
DRAW_LIST_ANTI_ALIASED_LINES_USE_TEX: int
187
DRAW_LIST_ANTI_ALIASED_FILL: int
188
DRAW_LIST_ALLOW_VTX_OFFSET: int
189
```
190
191
## Usage Examples
192
193
### Basic Shape Drawing
194
195
```python
196
import imgui
197
198
# Get draw list for current window
199
draw_list = imgui.get_window_draw_list()
200
201
# Get current cursor position as starting point
202
cursor_pos = imgui.get_cursor_screen_pos()
203
canvas_pos = cursor_pos
204
canvas_size = (200, 200)
205
206
# Reserve space for drawing
207
imgui.dummy(*canvas_size)
208
209
# Colors
210
white = imgui.get_color_u32_rgba(1.0, 1.0, 1.0, 1.0)
211
red = imgui.get_color_u32_rgba(1.0, 0.0, 0.0, 1.0)
212
green = imgui.get_color_u32_rgba(0.0, 1.0, 0.0, 1.0)
213
blue = imgui.get_color_u32_rgba(0.0, 0.0, 1.0, 1.0)
214
215
# Draw rectangle
216
draw_list.add_rect(
217
(canvas_pos[0] + 10, canvas_pos[1] + 10),
218
(canvas_pos[0] + 60, canvas_pos[1] + 60),
219
red, 0.0, 0, 2.0
220
)
221
222
# Draw filled rectangle
223
draw_list.add_rect_filled(
224
(canvas_pos[0] + 70, canvas_pos[1] + 10),
225
(canvas_pos[0] + 120, canvas_pos[1] + 60),
226
green
227
)
228
229
# Draw circle
230
draw_list.add_circle(
231
(canvas_pos[0] + 50, canvas_pos[1] + 100),
232
30, blue, 0, 2.0
233
)
234
235
# Draw filled circle
236
draw_list.add_circle_filled(
237
(canvas_pos[0] + 120, canvas_pos[1] + 100),
238
25, red
239
)
240
```
241
242
### Interactive Drawing Canvas
243
244
```python
245
# Interactive drawing example
246
drawing_canvas_size = (400, 300)
247
canvas_pos = imgui.get_cursor_screen_pos()
248
249
# Reserve space for canvas
250
imgui.invisible_button("canvas", *drawing_canvas_size)
251
draw_list = imgui.get_window_draw_list()
252
253
# Draw canvas background
254
canvas_color = imgui.get_color_u32_rgba(0.1, 0.1, 0.1, 1.0)
255
draw_list.add_rect_filled(
256
canvas_pos,
257
(canvas_pos[0] + drawing_canvas_size[0], canvas_pos[1] + drawing_canvas_size[1]),
258
canvas_color
259
)
260
261
# Handle mouse drawing
262
if imgui.is_item_hovered() and imgui.is_mouse_down(0):
263
mouse_pos = imgui.get_mouse_pos()
264
# Check if mouse is within canvas bounds
265
if (canvas_pos[0] <= mouse_pos[0] <= canvas_pos[0] + drawing_canvas_size[0] and
266
canvas_pos[1] <= mouse_pos[1] <= canvas_pos[1] + drawing_canvas_size[1]):
267
268
# Draw at mouse position
269
brush_color = imgui.get_color_u32_rgba(1.0, 1.0, 1.0, 1.0)
270
draw_list.add_circle_filled(mouse_pos, 3, brush_color)
271
272
# Canvas border
273
border_color = imgui.get_color_u32_rgba(0.5, 0.5, 0.5, 1.0)
274
draw_list.add_rect(
275
canvas_pos,
276
(canvas_pos[0] + drawing_canvas_size[0], canvas_pos[1] + drawing_canvas_size[1]),
277
border_color
278
)
279
```
280
281
### Complex Shape Drawing
282
283
```python
284
# Draw complex shapes
285
draw_list = imgui.get_window_draw_list()
286
start_pos = imgui.get_cursor_screen_pos()
287
288
# Draw a star shape using path
289
draw_list.path_clear()
290
center = (start_pos[0] + 100, start_pos[1] + 100)
291
outer_radius = 50
292
inner_radius = 25
293
num_points = 5
294
295
import math
296
297
for i in range(num_points * 2):
298
angle = i * math.pi / num_points
299
radius = outer_radius if i % 2 == 0 else inner_radius
300
x = center[0] + radius * math.cos(angle)
301
y = center[1] + radius * math.sin(angle)
302
draw_list.path_line_to((x, y))
303
304
# Fill the star
305
star_color = imgui.get_color_u32_rgba(1.0, 1.0, 0.0, 1.0)
306
draw_list.path_fill_convex(star_color)
307
308
# Reserve space
309
imgui.dummy(200, 200)
310
```
311
312
### Bezier Curves and Advanced Shapes
313
314
```python
315
# Draw Bezier curves
316
draw_list = imgui.get_window_draw_list()
317
start_pos = imgui.get_cursor_screen_pos()
318
319
# Cubic Bezier curve
320
p1 = (start_pos[0] + 20, start_pos[1] + 100)
321
p2 = (start_pos[0] + 60, start_pos[1] + 20)
322
p3 = (start_pos[0] + 140, start_pos[1] + 180)
323
p4 = (start_pos[0] + 180, start_pos[1] + 100)
324
325
curve_color = imgui.get_color_u32_rgba(0.0, 1.0, 1.0, 1.0)
326
draw_list.add_bezier_cubic(p1, p2, p3, p4, curve_color, 2.0)
327
328
# Draw control points
329
point_color = imgui.get_color_u32_rgba(1.0, 0.0, 0.0, 1.0)
330
for point in [p1, p2, p3, p4]:
331
draw_list.add_circle_filled(point, 3, point_color)
332
333
# Quadratic Bezier
334
q1 = (start_pos[0] + 220, start_pos[1] + 100)
335
q2 = (start_pos[0] + 260, start_pos[1] + 40)
336
q3 = (start_pos[0] + 300, start_pos[1] + 100)
337
338
draw_list.add_bezier_quadratic(q1, q2, q3, curve_color, 2.0)
339
340
imgui.dummy(320, 200)
341
```
342
343
### Text and Advanced Drawing
344
345
```python
346
# Custom text rendering and graphics
347
draw_list = imgui.get_window_draw_list()
348
pos = imgui.get_cursor_screen_pos()
349
350
# Draw text with custom positioning
351
text_color = imgui.get_color_u32_rgba(1.0, 1.0, 1.0, 1.0)
352
draw_list.add_text((pos[0] + 10, pos[1] + 10), text_color, "Custom Text")
353
354
# Draw a gradient-like effect using multiple rectangles
355
gradient_width = 200
356
gradient_height = 50
357
358
for i in range(gradient_width):
359
alpha = i / gradient_width
360
color = imgui.get_color_u32_rgba(alpha, 0.5, 1.0 - alpha, 1.0)
361
draw_list.add_line(
362
(pos[0] + i, pos[1] + 40),
363
(pos[0] + i, pos[1] + 40 + gradient_height),
364
color, 1.0
365
)
366
367
imgui.dummy(220, 100)
368
```
369
370
### Background and Foreground Drawing
371
372
```python
373
# Draw on background layer (behind all windows)
374
bg_draw_list = imgui.get_background_draw_list()
375
screen_size = imgui.get_main_viewport().size
376
377
# Draw grid pattern on background
378
grid_color = imgui.get_color_u32_rgba(0.2, 0.2, 0.2, 0.5)
379
grid_size = 50
380
381
for x in range(0, int(screen_size[0]), grid_size):
382
bg_draw_list.add_line((x, 0), (x, screen_size[1]), grid_color)
383
384
for y in range(0, int(screen_size[1]), grid_size):
385
bg_draw_list.add_line((0, y), (screen_size[0], y), grid_color)
386
387
# Draw on foreground layer (in front of all windows)
388
fg_draw_list = imgui.get_foreground_draw_list()
389
mouse_pos = imgui.get_mouse_pos()
390
391
# Draw crosshair at mouse position
392
crosshair_color = imgui.get_color_u32_rgba(1.0, 0.0, 0.0, 0.8)
393
crosshair_size = 20
394
395
fg_draw_list.add_line(
396
(mouse_pos[0] - crosshair_size, mouse_pos[1]),
397
(mouse_pos[0] + crosshair_size, mouse_pos[1]),
398
crosshair_color, 2.0
399
)
400
fg_draw_list.add_line(
401
(mouse_pos[0], mouse_pos[1] - crosshair_size),
402
(mouse_pos[0], mouse_pos[1] + crosshair_size),
403
crosshair_color, 2.0
404
)
405
```
406
407
### Clipping and Masking
408
409
```python
410
# Drawing with clipping regions
411
draw_list = imgui.get_window_draw_list()
412
pos = imgui.get_cursor_screen_pos()
413
414
# Set up clipping region
415
clip_min = (pos[0] + 20, pos[1] + 20)
416
clip_max = (pos[0] + 180, pos[1] + 180)
417
418
draw_list.push_clip_rect(clip_min[0], clip_min[1], clip_max[0], clip_max[1], True)
419
420
# Draw shapes that will be clipped
421
large_circle_color = imgui.get_color_u32_rgba(0.8, 0.2, 0.8, 1.0)
422
draw_list.add_circle_filled((pos[0] + 100, pos[1] + 100), 80, large_circle_color)
423
424
# Draw clipping region border (this won't be clipped)
425
draw_list.pop_clip_rect()
426
border_color = imgui.get_color_u32_rgba(1.0, 1.0, 0.0, 1.0)
427
draw_list.add_rect(clip_min, clip_max, border_color, 0.0, 0, 2.0)
428
429
imgui.dummy(200, 200)
430
```