Source code for simvx.core.nodes_2d.shapes

"""Line2D and Polygon2D -- 2D shape rendering nodes."""

from ..descriptors import Property
from ..math.types import Vec2
from ..properties import Colour
from .node2d import Node2D


[docs] class Line2D(Node2D): """Anti-aliased polyline with configurable width and colour. Stores a list of (x, y) points and draws connected line segments. Supports joint modes, end caps, and gradient colouring along the line. """ points = Property((), hint="List of (x, y) tuples") width = Property(2.0, range=(0.1, 1000.0), hint="Line width in pixels") colour = Colour((1.0, 1.0, 1.0, 1.0)) joint_mode = Property("sharp", enum=["sharp", "bevel", "round"], hint="Joint style") begin_cap_mode = Property("none", enum=["none", "round"], hint="Start cap style") end_cap_mode = Property("none", enum=["none", "round"], hint="End cap style") gradient = Property(None, hint="Optional list of (t, colour) for gradient along line") gizmo_colour = Colour((0.2, 0.9, 0.4, 0.7))
[docs] def draw(self, renderer): """Draw the polyline. Renderer must support draw_line().""" pts = self.points if len(pts) < 2: return # Apply full node transform (position + rotation + scale) transformed = self.transform_points([Vec2(p[0], p[1]) for p in pts]) for i in range(len(transformed) - 1): renderer.draw_line( (transformed[i].x, transformed[i].y), (transformed[i + 1].x, transformed[i + 1].y), colour=self.colour, thickness=self.width, )
[docs] def get_gizmo_lines(self) -> list[tuple[Vec2, Vec2]]: """Return the polyline as connected line segments in world space.""" pts = self.points if len(pts) < 2: return [] transformed = self.transform_points([Vec2(p[0], p[1]) for p in pts]) return [(transformed[i], transformed[i + 1]) for i in range(len(transformed) - 1)]
[docs] class Polygon2D(Node2D): """Filled polygon rendered from a list of vertices. Vertices are in local space and transformed by the node's position, rotation, and scale. Supports optional UV coordinates and texture. """ polygon = Property((), hint="List of (x, y) vertices") colour = Colour((1.0, 1.0, 1.0, 1.0)) uv = Property((), hint="Optional UV coordinates per vertex") texture = Property(None, hint="Texture source: file path, PNG bytes, or RGBA uint8 ndarray")
[docs] def draw(self, renderer): """Draw the filled polygon. Renderer must support draw_polygon().""" verts = self.polygon if len(verts) < 3: return # Apply full node transform (position + rotation + scale) transformed = self.transform_points([Vec2(v[0], v[1]) for v in verts]) renderer.draw_polygon([(t.x, t.y) for t in transformed], colour=self.colour)