simvx.graphics.draw2d¶
Line weight¶
A 2D weight is measured in the space of the points it is drawn with. A
thickness, a width and a circle radius are in the same units as the
positions passed beside them: under a Camera2D they are world units and
scale with zoom, and under screen_space=True (or inside the
screen_space() scope) they are device pixels, because the coordinates are.
One policy, every primitive, both drawing surfaces – the immediate one here and
the recording one the retained item pipeline captures through
(render2d.item_builder._OpRecorder).
The mechanism is that weights expand into geometry before the active transform is applied, never after: a thick line becomes an oriented quad and a thick rectangle outline becomes four bars in the caller’s own space, and those corners are then transformed like any other point. Expanding after the transform would fix the weight to post-camera pixels, which the retained path cannot reproduce – it captures camera-free geometry and applies the camera per-vertex at submit – so the same call would draw two different widths depending on which surface happened to record it.
The one exception, and it is shared by both surfaces: a weight of 1.0 or less is a hairline. It rides the 1-pixel line pipeline, which draws one device pixel whatever the camera is doing. The branch is taken on the weight as requested, so both surfaces always agree on which pipeline a call lands on.
Immediate-mode 2D drawing API for Vulkan backend.
Canonical API: one entry point per primitive, keyword-only colour/filled/thickness:
Draw2D.draw_rect(pos, size, *, colour=None, filled=False, thickness=1.0)
Draw2D.draw_line(a, b, *, colour=None, thickness=1.0)
Draw2D.draw_circle(center, radius, *, colour=None, filled=False, segments=32)
Draw2D.draw_text(text, pos, *, colour=None, scale=1.0)
Colour values are RGBA float tuples in [0, 1] (3-tuples default alpha to 1.0).
None means opaque white. Designers thinking in 0-255 / hex should use
simvx.core.properties.Colour.from_rgb255(...) or Colour.hex(...) to
convert to the canonical float form.
Every call appends one Op to Draw2D._ops; Draw2DPass walks that list
in submission order. Submission order is the GPU order; there is no other
ordering mechanism.
Module Contents¶
Classes¶
Vulkan-backed immediate-mode 2D drawing API. |
Data¶
API¶
- simvx.graphics.draw2d.__all__¶
[‘Draw2D’, ‘UI_VERTEX_DTYPE’]
- class simvx.graphics.draw2d.Draw2D¶
Bases:
simvx.graphics.draw2d_transform.Draw2DTransformMixin,simvx.graphics.draw2d_text.Draw2DTextMixin,simvx.graphics.draw2d_texture.Draw2DTextureMixinVulkan-backed immediate-mode 2D drawing API.
Owns the ordered ops list (
_ops) and the scissor clip stack (_clip_stack/_current_clip). Every Draw2D submission appends a singleOpto_ops;Draw2DPasswalks the list in order and coalesces adjacent same-(kind, clip, tex_id) ops into one GPU draw. Submission order is the GPU order; there is no other ordering mechanism.push_clip/pop_clip/reset_clipare the only public hooks that mutate state without emitting an op.- classmethod push_post_layer(band: int) None¶
Enter a per-post CanvasLayer band: tag every op emitted until pop (web).
Mirrors :meth:
push_screen_transformas a context the tree walk opens when it reaches a CanvasLayer with anenvironmentset; the band is itslayervalue (the same key the desktop item pipeline bands on). Stored on a one-deep stack: a post CanvasLayer never nests inside another post CanvasLayer, so a single slot + saved-value suffices.
- classmethod pop_post_layer() None¶
Leave the current per-post CanvasLayer band (restore the previous).
- classmethod push_clip(x: int, y: int, w: int, h: int) None¶
Push a scissor clip rect; nested clips intersect with the current clip.
- classmethod pop_clip() None¶
Pop the last clip rect, restoring the previous one.
- classmethod reset_clip() None¶
Clear the clip stack and current clip, restoring full-screen drawing.
- classmethod draw_rect(pos, size, *, colour=None, filled=False, thickness=1.0, screen_space=False, blend='alpha') None¶
Draw a rectangle. filled=False draws an outline, filled=True fills the rect.
thicknesscontrols outline weight (filled=False). A weight of 1 or less is a hairline on the line pipeline; a heavier one becomes four filled bars grown inward from the rectangle’s bounds, measured in the same units asposandsize(see the weight policy in this module’s docstring).screen_space=Truebypasses the active Camera2D transform (HUDs, minimaps, overlays).blendis one of"alpha"(default),"add"(additive glow/flash), or"multiply"(dst*src darkening overlay); it applies to the filled path and thick outlines (hairline outlines always alpha-blend on the line pipeline).
- classmethod draw_line(a, b, *, colour=None, thickness=1.0, screen_space=False) None¶
Draw a line from a to b.
thickness <= 1rides the 1-px line pipeline;thickness > 1emits an oriented filled quad with perpendicular offsets so the weight is GPU-honoured rather than driver-clamped. The quad is built aroundaandbbefore the active transform is applied, so the weight is in the same units as the endpoints (see the weight policy in this module’s docstring).screen_space=Truebypasses the active Camera2D transform.
- classmethod draw_lines(points, closed=True, colour=None)¶
Draw a polyline (optionally closed) through the given points.
- classmethod draw_circle(center, radius, *, colour=None, filled=False, segments=32, screen_space=False) None¶
Draw a circle. filled=False draws an outline, filled=True fills a triangle fan.
radiusis in the same units ascenter(see the weight policy in this module’s docstring), so a zoomed camera scales it. The ring is built in those units and its points are transformed, so a rotated or non-uniform transform draws the ellipse it should rather than a circle of the mean scale. Setscreen_space=Trueto bypass the active Camera2D transform.
- classmethod fill_triangle(x1, y1, x2, y2, x3, y3, *, colour=None)¶
Emit a single filled triangle.
- classmethod fill_quad(x1, y1, x2, y2, x3, y3, x4, y4, *, colour=None)¶
Emit a filled quad from four arbitrary corners (two triangles).
- classmethod draw_thick_line(x1, y1, x2, y2, width=2.0, *, colour=None)¶
Draw a thick line as a filled quad using perpendicular offsets.
widthis in the same units as the endpoints: the offsets are applied before the active transform, as the weight policy in this module’s docstring requires.
- classmethod draw_polygon(vertices, *, colour=None, filled=True, blend='alpha')¶
Fill or outline an arbitrary polygon.
filled=True(default) triangulates via ear-clipping so concave shapes render correctly. Convex polygons hit a fast triangle-fan path.filled=Falseemits a closed line ring.blendis one of"alpha"(default),"add", or"multiply"and applies to the filled path (outlines always alpha-blend on the line pipeline).
- classmethod fill_rect_gradient(x, y, w, h, colour_top, colour_bottom)¶
Fill rect with vertical gradient (top colour -> bottom colour).
- classmethod clear(r=0, g=0, b=0)¶
- classmethod present()¶
- classmethod push_transform(a, b, c, d, tx, ty)¶
- classmethod pop_transform()¶
- classmethod push_identity()¶
- classmethod push_screen_transform(a, b, c, d, tx, ty)¶
- classmethod screen_space()¶
- classmethod set_font(path: str | None = None, size: int = 48) None¶
- classmethod draw_text(text, pos=None, *, colour=None, scale=1.0, rect=None, alignment='left', vertical_alignment='top', fit_to_width=False, min_scale=None, outline=0.0, outline_colour=None, screen_space=False, cell_width=0.0)¶
- classmethod text_height(text, scale=1.0)¶
- classmethod text_size(text, scale=1.0)¶
- classmethod fit_scale(text, max_width, *, base_scale=1.0, min_scale=None, cell_width=0.0)¶
- classmethod text_width(text, scale=1, *, cell_width=0.0)¶
- classmethod register_texture(png_data: bytes) int¶
- classmethod register_texture_with_id(texture_id: int, png_data: bytes) None¶
- classmethod draw_texture(texture_id: int, pos, size, *, colour: tuple[float, ...] | None = None, rotation: float = 0.0, blend: str = 'alpha', screen_space: bool = False)¶
- classmethod draw_texture_region(texture_id: int, pos, size, uv0=(0.0, 0.0), uv1=(1.0, 1.0), colour: tuple[float, ...] | None = None, rotation: float = 0.0, *, blend: str = 'alpha', screen_space: bool = False)¶
- classmethod draw_image(path: str | pathlib.Path, x: float, y: float, w: float, h: float, *, colour: tuple[float, ...] | None = None, rotation: float = 0.0, filter: str = 'linear', blend: str = 'alpha')¶
- classmethod draw_nine_patch(texture_id: int, x: float, y: float, w: float, h: float, tex_w: float, tex_h: float, margin_left: float = 0.0, margin_right: float = 0.0, margin_top: float = 0.0, margin_bottom: float = 0.0, draw_centre: bool = True, colour: tuple[float, ...] | None = None)¶