__docformat__ = "reStructuredText"
from typing import TYPE_CHECKING, ClassVar, NamedTuple, Optional, Sequence, Tuple, Type
if TYPE_CHECKING:
from .shapes import Shape
from types import TracebackType
import math
from ._chipmunk_cffi import ffi, lib
from .body import Body
from .transform import Transform
from .vec2d import Vec2d
_DrawFlags = int
class SpaceDebugColor(NamedTuple):
"""Color tuple used by the debug drawing API."""
r: float
g: float
b: float
a: float
def as_int(self) -> Tuple[int, int, int, int]:
"""Return the color as a tuple of ints, where each value is rounded.
>>> SpaceDebugColor(0, 51.1, 101.9, 255).as_int()
(0, 51, 102, 255)
"""
return round(self[0]), round(self[1]), round(self[2]), round(self[3])
def as_float(self) -> Tuple[float, float, float, float]:
"""Return the color as a tuple of floats, each value divided by 255.
>>> SpaceDebugColor(0, 51, 102, 255).as_float()
(0.0, 0.2, 0.4, 1.0)
"""
return self[0] / 255.0, self[1] / 255.0, self[2] / 255.0, self[3] / 255.0
[文档]
class SpaceDebugDrawOptions(object):
"""SpaceDebugDrawOptions configures debug drawing.
If appropriate its usually easy to use the supplied draw implementations
directly: pymunk.pygame_util, pymunk.pyglet_util and pymunk.matplotlib_util.
"""
DRAW_SHAPES: ClassVar[_DrawFlags] = lib.CP_SPACE_DEBUG_DRAW_SHAPES
"""Draw shapes.
Use on the flags property to control if shapes should be drawn or not.
"""
DRAW_CONSTRAINTS: ClassVar[_DrawFlags] = lib.CP_SPACE_DEBUG_DRAW_CONSTRAINTS
"""Draw constraints.
Use on the flags property to control if constraints should be drawn or not.
"""
DRAW_COLLISION_POINTS: ClassVar[
_DrawFlags
] = lib.CP_SPACE_DEBUG_DRAW_COLLISION_POINTS
"""Draw collision points.
Use on the flags property to control if collision points should be drawn or
not.
"""
shape_dynamic_color: SpaceDebugColor = SpaceDebugColor(52, 152, 219, 255)
shape_static_color: SpaceDebugColor = SpaceDebugColor(149, 165, 166, 255)
shape_kinematic_color: SpaceDebugColor = SpaceDebugColor(39, 174, 96, 255)
shape_sleeping_color: SpaceDebugColor = SpaceDebugColor(114, 148, 168, 255)
[文档]
def __init__(self) -> None:
_options = ffi.new("cpSpaceDebugDrawOptions *")
self._options = _options
self._options.transform = Transform.identity()
self.shape_outline_color = SpaceDebugColor(44, 62, 80, 255)
self.constraint_color = SpaceDebugColor(142, 68, 173, 255)
self.collision_point_color = SpaceDebugColor(231, 76, 60, 255)
# Set to false to bypass chipmunk shape drawing code
self._use_chipmunk_debug_draw = True
_options.drawCircle = lib.ext_cpSpaceDebugDrawCircleImpl
_options.drawSegment = lib.ext_cpSpaceDebugDrawSegmentImpl
_options.drawFatSegment = lib.ext_cpSpaceDebugDrawFatSegmentImpl
_options.drawPolygon = lib.ext_cpSpaceDebugDrawPolygonImpl
_options.drawDot = lib.ext_cpSpaceDebugDrawDotImpl
_options.colorForShape = lib.ext_cpSpaceDebugDrawColorForShapeImpl
self.flags = (
SpaceDebugDrawOptions.DRAW_SHAPES
| SpaceDebugDrawOptions.DRAW_CONSTRAINTS
| SpaceDebugDrawOptions.DRAW_COLLISION_POINTS
)
def _get_shape_outline_color(self) -> SpaceDebugColor:
return self._c(self._options.shapeOutlineColor)
def _set_shape_outline_color(self, c: SpaceDebugColor) -> None:
self._options.shapeOutlineColor = c
shape_outline_color = property(
_get_shape_outline_color,
_set_shape_outline_color,
doc="""The outline color of shapes.
Should be a tuple of 4 ints between 0 and 255 (r,g,b,a).
Example:
>>> import pymunk
>>> s = pymunk.Space()
>>> c = pymunk.Circle(s.static_body, 10)
>>> s.add(c)
>>> options = pymunk.SpaceDebugDrawOptions()
>>> s.debug_draw(options)
draw_circle (Vec2d(0.0, 0.0), 0.0, 10.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=149.0, g=165.0, b=166.0, a=255.0))
>>> options.shape_outline_color = (10,20,30,40)
>>> s.debug_draw(options)
draw_circle (Vec2d(0.0, 0.0), 0.0, 10.0, SpaceDebugColor(r=10.0, g=20.0, b=30.0, a=40.0), SpaceDebugColor(r=149.0, g=165.0, b=166.0, a=255.0))
""",
)
def _get_constraint_color(self) -> SpaceDebugColor:
return self._c(self._options.constraintColor)
def _set_constraint_color(self, c: SpaceDebugColor) -> None:
self._options.constraintColor = c
constraint_color = property(
_get_constraint_color,
_set_constraint_color,
doc="""The color of constraints.
Should be a tuple of 4 ints between 0 and 255 (r,g,b,a).
Example:
>>> import pymunk
>>> s = pymunk.Space()
>>> b = pymunk.Body(1, 10)
>>> j = pymunk.PivotJoint(s.static_body, b, (0,0))
>>> s.add(j)
>>> options = pymunk.SpaceDebugDrawOptions()
>>> s.debug_draw(options)
draw_dot (5.0, Vec2d(0.0, 0.0), SpaceDebugColor(r=142.0, g=68.0, b=173.0, a=255.0))
draw_dot (5.0, Vec2d(0.0, 0.0), SpaceDebugColor(r=142.0, g=68.0, b=173.0, a=255.0))
>>> options.constraint_color = (10,20,30,40)
>>> s.debug_draw(options)
draw_dot (5.0, Vec2d(0.0, 0.0), SpaceDebugColor(r=10.0, g=20.0, b=30.0, a=40.0))
draw_dot (5.0, Vec2d(0.0, 0.0), SpaceDebugColor(r=10.0, g=20.0, b=30.0, a=40.0))
""",
)
def _get_collision_point_color(self) -> SpaceDebugColor:
return self._c(self._options.collisionPointColor)
def _set_collision_point_color(self, c: SpaceDebugColor) -> None:
self._options.collisionPointColor = c
collision_point_color = property(
_get_collision_point_color,
_set_collision_point_color,
doc="""The color of collisions.
Should be a tuple of 4 ints between 0 and 255 (r,g,b,a).
Example:
>>> import pymunk
>>> s = pymunk.Space()
>>> b = pymunk.Body(1,10)
>>> c1 = pymunk.Circle(b, 10)
>>> c2 = pymunk.Circle(s.static_body, 10)
>>> s.add(b, c1, c2)
>>> s.step(1)
>>> options = pymunk.SpaceDebugDrawOptions()
>>> s.debug_draw(options)
draw_circle (Vec2d(0.0, 0.0), 0.0, 10.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=52.0, g=152.0, b=219.0, a=255.0))
draw_circle (Vec2d(0.0, 0.0), 0.0, 10.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=149.0, g=165.0, b=166.0, a=255.0))
draw_segment (Vec2d(8.0, 0.0), Vec2d(-8.0, 0.0), SpaceDebugColor(r=231.0, g=76.0, b=60.0, a=255.0))
>>> options.collision_point_color = (10,20,30,40)
>>> s.debug_draw(options)
draw_circle (Vec2d(0.0, 0.0), 0.0, 10.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=52.0, g=152.0, b=219.0, a=255.0))
draw_circle (Vec2d(0.0, 0.0), 0.0, 10.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=149.0, g=165.0, b=166.0, a=255.0))
draw_segment (Vec2d(8.0, 0.0), Vec2d(-8.0, 0.0), SpaceDebugColor(r=10.0, g=20.0, b=30.0, a=40.0))
""",
)
def __enter__(self) -> None:
pass
def __exit__(
self,
type: Optional[Type[BaseException]],
value: Optional[BaseException],
traceback: Optional["TracebackType"],
) -> None:
pass
def _c(self, color: ffi.CData) -> SpaceDebugColor:
return SpaceDebugColor(color.r, color.g, color.b, color.a)
def _get_flags(self) -> _DrawFlags:
return self._options.flags
def _set_flags(self, f: _DrawFlags) -> None:
self._options.flags = f
flags = property(
_get_flags,
_set_flags,
doc="""Bit flags which of shapes, joints and collisions should be drawn.
By default all 3 flags are set, meaning shapes, joints and collisions
will be drawn.
Example using the basic text only DebugDraw implementation (normally
you would the desired backend instead, such as
`pygame_util.DrawOptions` or `pyglet_util.DrawOptions`):
>>> import pymunk
>>> s = pymunk.Space()
>>> b = pymunk.Body()
>>> c = pymunk.Circle(b, 10)
>>> c.mass = 3
>>> s.add(b, c)
>>> s.add(pymunk.Circle(s.static_body, 3))
>>> s.step(0.01)
>>> options = pymunk.SpaceDebugDrawOptions()
>>> # Only draw the shapes, nothing else:
>>> options.flags = pymunk.SpaceDebugDrawOptions.DRAW_SHAPES
>>> s.debug_draw(options)
draw_circle (Vec2d(0.0, 0.0), 0.0, 10.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=52.0, g=152.0, b=219.0, a=255.0))
draw_circle (Vec2d(0.0, 0.0), 0.0, 3.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=149.0, g=165.0, b=166.0, a=255.0))
>>> # Draw the shapes and collision points:
>>> options.flags = pymunk.SpaceDebugDrawOptions.DRAW_SHAPES
>>> options.flags |= pymunk.SpaceDebugDrawOptions.DRAW_COLLISION_POINTS
>>> s.debug_draw(options)
draw_circle (Vec2d(0.0, 0.0), 0.0, 10.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=52.0, g=152.0, b=219.0, a=255.0))
draw_circle (Vec2d(0.0, 0.0), 0.0, 3.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=149.0, g=165.0, b=166.0, a=255.0))
draw_segment (Vec2d(1.0, 0.0), Vec2d(-8.0, 0.0), SpaceDebugColor(r=231.0, g=76.0, b=60.0, a=255.0))
""",
)
def _get_transform(self) -> Transform:
t = self._options.transform
return Transform(t.a, t.b, t.c, t.d, t.tx, t.ty)
def _set_transform(self, t: Transform) -> None:
self._options.transform = t
transform = property(
_get_transform,
_set_transform,
doc="""The transform is applied before drawing, e.g for scaling or
translation.
Example:
>>> import pymunk
>>> s = pymunk.Space()
>>> c = pymunk.Circle(s.static_body, 10)
>>> s.add(c)
>>> options = pymunk.SpaceDebugDrawOptions()
>>> s.debug_draw(options)
draw_circle (Vec2d(0.0, 0.0), 0.0, 10.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=149.0, g=165.0, b=166.0, a=255.0))
>>> options.transform = pymunk.Transform.scaling(2)
>>> s.debug_draw(options)
draw_circle (Vec2d(0.0, 0.0), 0.0, 20.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=149.0, g=165.0, b=166.0, a=255.0))
>>> options.transform = pymunk.Transform.translation(2,3)
>>> s.debug_draw(options)
draw_circle (Vec2d(2.0, 3.0), 0.0, 10.0, SpaceDebugColor(r=44.0, g=62.0, b=80.0, a=255.0), SpaceDebugColor(r=149.0, g=165.0, b=166.0, a=255.0))
.. Note::
Not all tranformations are supported by the debug drawing logic.
Uniform scaling and translation are supported, but not rotation,
linear stretching or shearing.
""",
)
[文档]
def draw_circle(
self,
pos: Vec2d,
angle: float,
radius: float,
outline_color: SpaceDebugColor,
fill_color: SpaceDebugColor,
) -> None:
print("draw_circle", (pos, angle, radius, outline_color, fill_color))
[文档]
def draw_segment(self, a: Vec2d, b: Vec2d, color: SpaceDebugColor) -> None:
print("draw_segment", (a, b, color))
[文档]
def draw_fat_segment(
self,
a: Vec2d,
b: Vec2d,
radius: float,
outline_color: SpaceDebugColor,
fill_color: SpaceDebugColor,
) -> None:
print("draw_fat_segment", (a, b, radius, outline_color, fill_color))
[文档]
def draw_polygon(
self,
verts: Sequence[Vec2d],
radius: float,
outline_color: SpaceDebugColor,
fill_color: SpaceDebugColor,
) -> None:
print("draw_polygon", (verts, radius, outline_color, fill_color))
[文档]
def draw_dot(self, size: float, pos: Vec2d, color: SpaceDebugColor) -> None:
print("draw_dot", (size, pos, color))
[文档]
def draw_shape(self, shape: "Shape") -> None:
print("draw_shape", shape)
[文档]
def color_for_shape(self, shape: "Shape") -> SpaceDebugColor:
if hasattr(shape, "color"):
return SpaceDebugColor(*shape.color)
color = self.shape_dynamic_color
if shape.body != None:
if shape.body.body_type == Body.STATIC:
color = self.shape_static_color
elif shape.body.body_type == Body.KINEMATIC:
color = self.shape_kinematic_color
elif shape.body.is_sleeping:
color = self.shape_sleeping_color
return color