Source code for easymunk.pyglet.draw_options

import math
from typing import TYPE_CHECKING, Any, Optional, Sequence, Type
from functools import lru_cache
import pyglet  # type: ignore

from ..drawing import DrawOptions as DrawOptionsBase, Color
from ..linalg import Vec2d

if TYPE_CHECKING:
    from types import TracebackType


[docs]class DrawOptions(DrawOptionsBase): _COLOR = DrawOptionsBase._COLOR def __init__(self, **kwargs: Any) -> None: """Draw a Space object. Args: kwargs: You can optionally pass in a pyglet.graphics.Batch. If a batch is given all drawing will use this batch to draw on. If no batch is given a a new batch will be used for the drawing. Remember that if you pass in your own batch you need to call draw on it yourself. """ self.new_batch = False if "batch" not in kwargs: self.new_batch = True else: self.batch = kwargs["batch"] super(DrawOptions, self).__init__() def __enter__(self) -> None: if self.new_batch: self.batch = pyglet.graphics.Batch() def __exit__( self, typ: Optional[Type[BaseException]], value: Optional[BaseException], traceback: Optional["TracebackType"], ): if self.new_batch: self.batch.draw()
[docs] def draw_circle( self, pos: Vec2d, radius: float, angle: float = 0.0, outline_color: Color = _COLOR, fill_color: Color = _COLOR, ) -> None: circle_center = pos # http://slabode.exofire.net/circle_draw.shtml num_segments = int(4 * math.sqrt(radius)) theta = 2 * math.pi / num_segments c = math.cos(theta) s = math.sin(theta) x = radius # we start at angle 0 y: float = 0 ps = [] for i in range(num_segments): ps += [Vec2d(circle_center.x + x, circle_center.y + y)] t = x x = c * x - s * y y = s * t + c * y mode = pyglet.gl.GL_TRIANGLE_STRIP ps2 = [ps[0]] for i in range(1, int(len(ps) + 1 / 2)): ps2.append(ps[i]) ps2.append(ps[-i]) ps = ps2 vs = [] for p in [ps[0]] + ps + [ps[-1]]: vs += [p.x, p.y] cc = circle_center + Vec2d(radius, 0).rotated(angle) cvs = [circle_center.x, circle_center.y, cc.x, cc.y] bg = pyglet.graphics.OrderedGroup(0) fg = pyglet.graphics.OrderedGroup(1) n = len(vs) // 2 self.batch.add(len(vs) // 2, mode, bg, ("v2f", vs), ("c4B", fill_color * n)) self.batch.add( 2, pyglet.gl.GL_LINES, fg, ("v2f", cvs), ("c4B", outline_color * 2) )
[docs] def draw_segment(self, a: Vec2d, b: Vec2d, color: Color = _COLOR) -> None: pv1 = a pv2 = b line = (int(pv1.x), int(pv1.y), int(pv2.x), int(pv2.y)) self.batch.add(2, pyglet.gl.GL_LINES, None, ("v2i", line), ("c4B", color * 2))
[docs] def draw_fat_segment( self, a: Vec2d, b: Vec2d, radius: float = 0.0, outline_color: Color = _COLOR, fill_color: Color = _COLOR, ) -> None: pv1 = a pv2 = b d = pv2 - pv1 atan = -math.atan2(d.x, d.y) radius = max(radius, 1) dx = radius * math.cos(atan) dy = radius * math.sin(atan) p1 = pv1 + Vec2d(dx, dy) p2 = pv1 - Vec2d(dx, dy) p3 = pv2 + Vec2d(dx, dy) p4 = pv2 - Vec2d(dx, dy) vs = [i for xy in [p1, p2, p3] + [p2, p3, p4] for i in xy] n = len(vs) // 2 self.batch.add( n, pyglet.gl.GL_TRIANGLES, None, ("v2f", vs), ("c4B", fill_color * n), ) self.draw_circle(a, radius, 0, fill_color, fill_color) self.draw_circle(b, radius, 0, fill_color, fill_color)
[docs] def draw_polygon( self, verts: Sequence[Vec2d], radius: float = 0.0, outline_color: Color = _COLOR, fill_color: Color = _COLOR, ) -> None: mode = pyglet.gl.GL_TRIANGLE_STRIP n = len(verts) mid = len(verts) // 2 if radius >= 3: # print("POLY", verts) pass vs = [] for i in range(mid): vs += [verts[i].x, verts[i].y] vs += [verts[n - 1 - i].x, verts[n - 1 - i].y] if n % 2: vs += [verts[mid].x, verts[mid].y] vs = [vs[0], vs[1]] + vs + [vs[-2], vs[-1]] n = len(vs) // 2 self.batch.add(n, mode, None, ("v2f", vs), ("c4B", fill_color * n)) if radius > 0: for i in range(len(verts)): a = verts[i] b = verts[(i + 1) % len(verts)] self.draw_fat_segment(a, b, radius, outline_color, outline_color)
[docs] def draw_dot(self, size: float, pos: Vec2d, color: Color) -> None: self.batch.add( 1, pyglet.gl.GL_POINTS, _gr_point_size_cls()(size), ("v2f", pos), ("c4B", color * 1), )
@lru_cache() def _gr_point_size_cls(): # We wrap class creation since tests may fail if pyglet cannot find the # display class GrPointSize(pyglet.graphics.Group): # type: ignore """ This pyglet rendering group sets a specific point size. """ def __init__(self, size: float = 1.0) -> None: super().__init__() self.size = size def set_state(self) -> None: pyglet.gl.glPointSize(self.size) def unset_state(self) -> None: pyglet.gl.glPointSize(1.0) return GrPointSize