Skip to content

Commit 3591517

Browse files
committed
Readd data to collision callbacks, fix tests
1 parent 1b4b88e commit 3591517

17 files changed

+280
-268
lines changed

pymunk/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
"ContactPoint",
5959
"ContactPointSet",
6060
"Arbiter",
61-
"CollisionHandler",
6261
"BB",
6362
"ShapeFilter",
6463
"Transform",
@@ -80,7 +79,6 @@
8079
from .arbiter import Arbiter
8180
from .bb import BB
8281
from .body import Body
83-
from .collision_handler import CollisionHandler
8482
from .constraints import *
8583
from .contact_point_set import ContactPoint, ContactPointSet
8684
from .query_info import PointQueryInfo, SegmentQueryInfo, ShapeQueryInfo

pymunk/_callbacks.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,23 +203,27 @@ def ext_cpCollisionBeginFunc(
203203
_arb: ffi.CData, _space: ffi.CData, data: ffi.CData
204204
) -> None:
205205
handler = ffi.from_handle(data)
206-
handler._begin(Arbiter(_arb, handler._space), handler._space)
206+
handler._begin(Arbiter(_arb, handler._space), handler._space, handler.data["begin"])
207207

208208

209209
@ffi.def_extern()
210210
def ext_cpCollisionPreSolveFunc(
211211
_arb: ffi.CData, _space: ffi.CData, data: ffi.CData
212212
) -> None:
213213
handler = ffi.from_handle(data)
214-
handler._pre_solve(Arbiter(_arb, handler._space), handler._space)
214+
handler._pre_solve(
215+
Arbiter(_arb, handler._space), handler._space, handler.data["pre_solve"]
216+
)
215217

216218

217219
@ffi.def_extern()
218220
def ext_cpCollisionPostSolveFunc(
219221
_arb: ffi.CData, _space: ffi.CData, data: ffi.CData
220222
) -> None:
221223
handler = ffi.from_handle(data)
222-
handler._post_solve(Arbiter(_arb, handler._space), handler._space)
224+
handler._post_solve(
225+
Arbiter(_arb, handler._space), handler._space, handler.data["post_solve"]
226+
)
223227

224228

225229
@ffi.def_extern()
@@ -234,7 +238,9 @@ def ext_cpCollisionSeparateFunc(
234238
# this try is needed since a separate callback will be called
235239
# if a colliding object is removed, regardless if its in a
236240
# step or not. Meaning the unlock must succeed
237-
handler._separate(Arbiter(_arb, handler._space), handler._space)
241+
handler._separate(
242+
Arbiter(_arb, handler._space), handler._space, handler.data["separate"]
243+
)
238244
finally:
239245
handler._space._locked = orig_locked
240246

pymunk/collision_handler.py renamed to pymunk/_collision_handler.py

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
__docformat__ = "reStructuredText"
22

3-
from typing import TYPE_CHECKING, Any, Callable
3+
from typing import TYPE_CHECKING, Any, Callable, Optional
44

55
if TYPE_CHECKING:
66
from .space import Space
77

88
from ._chipmunk_cffi import ffi, lib
99
from .arbiter import Arbiter
1010

11-
_CollisionCallback = Callable[[Arbiter, "Space"], None]
11+
_CollisionCallback = Callable[[Arbiter, "Space", Any], None]
1212

1313

1414
class CollisionHandler(object):
@@ -41,10 +41,10 @@ def __init__(self, _handler: Any, space: "Space") -> None:
4141
self._handler.userData = self._userData
4242

4343
self._space = space
44-
self._begin: _CollisionCallback = CollisionHandler.do_nothing
45-
self._pre_solve: _CollisionCallback = CollisionHandler.do_nothing
46-
self._post_solve: _CollisionCallback = CollisionHandler.do_nothing
47-
self._separate: _CollisionCallback = CollisionHandler.do_nothing
44+
self._begin: Optional[_CollisionCallback] = None
45+
self._pre_solve: Optional[_CollisionCallback] = None
46+
self._post_solve: Optional[_CollisionCallback] = None
47+
self._separate: Optional[_CollisionCallback] = None
4848

4949
self._data: dict[Any, Any] = {}
5050

@@ -60,7 +60,7 @@ def data(self) -> dict[Any, Any]:
6060
return self._data
6161

6262
@property
63-
def begin(self) -> _CollisionCallback:
63+
def begin(self) -> Optional[_CollisionCallback]:
6464
"""Two shapes just started touching for the first time this step.
6565
6666
``func(arbiter, space, data)``
@@ -74,16 +74,16 @@ def begin(self) -> _CollisionCallback:
7474
return self._begin
7575

7676
@begin.setter
77-
def begin(self, func: _CollisionCallback) -> None:
77+
def begin(self, func: Optional[_CollisionCallback]) -> None:
7878
self._begin = func
7979

80-
if self._begin == CollisionHandler.do_nothing:
80+
if self._begin == None:
8181
self._handler.beginFunc = ffi.addressof(lib, "DoNothing")
8282
else:
8383
self._handler.beginFunc = lib.ext_cpCollisionBeginFunc
8484

8585
@property
86-
def pre_solve(self) -> _CollisionCallback:
86+
def pre_solve(self) -> Optional[_CollisionCallback]:
8787
"""Two shapes are touching during this step.
8888
8989
``func(arbiter, space, data)``
@@ -96,16 +96,16 @@ def pre_solve(self) -> _CollisionCallback:
9696
return self._pre_solve
9797

9898
@pre_solve.setter
99-
def pre_solve(self, func: _CollisionCallback) -> None:
99+
def pre_solve(self, func: Optional[_CollisionCallback]) -> None:
100100
self._pre_solve = func
101101

102-
if self._pre_solve == CollisionHandler.do_nothing:
102+
if self._pre_solve == None:
103103
self._handler.preSolveFunc = ffi.addressof(lib, "DoNothing")
104104
else:
105105
self._handler.preSolveFunc = lib.ext_cpCollisionPreSolveFunc
106106

107107
@property
108-
def post_solve(self) -> _CollisionCallback:
108+
def post_solve(self) -> Optional[_CollisionCallback]:
109109
"""Two shapes are touching and their collision response has been
110110
processed.
111111
@@ -118,16 +118,16 @@ def post_solve(self) -> _CollisionCallback:
118118
return self._post_solve
119119

120120
@post_solve.setter
121-
def post_solve(self, func: _CollisionCallback) -> None:
121+
def post_solve(self, func: Optional[_CollisionCallback]) -> None:
122122
self._post_solve = func
123123

124-
if self._post_solve == CollisionHandler.do_nothing:
124+
if self._post_solve == None:
125125
self._handler.postSolveFunc = ffi.addressof(lib, "DoNothing")
126126
else:
127127
self._handler.postSolveFunc = lib.ext_cpCollisionPostSolveFunc
128128

129129
@property
130-
def separate(self) -> _CollisionCallback:
130+
def separate(self) -> Optional[_CollisionCallback]:
131131
"""Two shapes have just stopped touching for the first time this
132132
step.
133133
@@ -140,20 +140,10 @@ def separate(self) -> _CollisionCallback:
140140
return self._separate
141141

142142
@separate.setter
143-
def separate(self, func: _CollisionCallback) -> None:
143+
def separate(self, func: Optional[_CollisionCallback]) -> None:
144144
self._separate = func
145145

146-
if self._separate == CollisionHandler.do_nothing:
146+
if self._separate == None:
147147
self._handler.separateFunc = ffi.addressof(lib, "DoNothing")
148148
else:
149149
self._handler.separateFunc = lib.ext_cpCollisionSeparateFunc
150-
151-
@staticmethod
152-
def do_nothing(arbiter: Arbiter, space: "Space") -> None:
153-
"""The default do nothing method used for the post_solve and seprate
154-
callbacks.
155-
156-
Note that its more efficient to set this method than to define your own
157-
do nothing method.
158-
"""
159-
return

pymunk/examples/arrows.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def post_solve_arrow_hit(arbiter, space, data):
4949
arrow_body,
5050
other_body,
5151
position,
52-
data["flying_arrows"],
52+
data,
5353
)
5454

5555

@@ -98,9 +98,9 @@ def main():
9898
space.add(arrow_body, arrow_shape)
9999

100100
flying_arrows: list[pymunk.Body] = []
101-
handler = space.add_collision_handler(0, 1)
102-
handler.data["flying_arrows"] = flying_arrows
103-
handler.post_solve = post_solve_arrow_hit
101+
space.set_collision_callback(
102+
0, 1, post_solve=post_solve_arrow_hit, data=flying_arrows
103+
)
104104

105105
start_time = 0
106106
while running:

pymunk/examples/balls_and_lines.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
"""This example lets you dynamically create static walls and dynamic balls
1+
"""This example lets you dynamically create static walls and dynamic balls"""
22

3-
"""
43
__docformat__ = "reStructuredText"
54

65
import pygame
@@ -24,7 +23,7 @@ def mouse_coll_func(arbiter, space, data):
2423
"""Simple callback that increases the radius of circles touching the mouse"""
2524
s1, s2 = arbiter.shapes
2625
s2.unsafe_set_radius(s2.radius + 0.15)
27-
return False
26+
arbiter.process_collision = False
2827

2928

3029
def main():
@@ -47,9 +46,9 @@ def main():
4746
mouse_shape.collision_type = COLLTYPE_MOUSE
4847
space.add(mouse_body, mouse_shape)
4948

50-
space.add_collision_handler(
51-
COLLTYPE_MOUSE, COLLTYPE_BALL
52-
).pre_solve = mouse_coll_func
49+
space.set_collision_callback(
50+
COLLTYPE_MOUSE, COLLTYPE_BALL, pre_solve=mouse_coll_func
51+
)
5352

5453
### Static line
5554
line_point1 = None

pymunk/examples/breakout.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
"""Very simple breakout clone. A circle shape serves as the paddle, then
2-
breakable bricks constructed of Poly-shapes.
1+
"""Very simple breakout clone. A circle shape serves as the paddle, then
2+
breakable bricks constructed of Poly-shapes.
33
4-
The code showcases several pymunk concepts such as elasitcity, impulses,
4+
The code showcases several pymunk concepts such as elasitcity, impulses,
55
constant object speed, joints, collision handlers and post step callbacks.
66
"""
77

@@ -48,7 +48,7 @@ def constant_velocity(body, gravity, damping, dt):
4848
def setup_level(space, player_body):
4949

5050
# Remove balls and bricks
51-
for s in space.shapes[:]:
51+
for s in list(space.shapes):
5252
if s.body.body_type == pymunk.Body.DYNAMIC and s.body not in [player_body]:
5353
space.remove(s.body, s)
5454

@@ -76,8 +76,9 @@ def remove_brick(arbiter, space, data):
7676
brick_shape = arbiter.shapes[0]
7777
space.remove(brick_shape, brick_shape.body)
7878

79-
h = space.add_collision_handler(collision_types["brick"], collision_types["ball"])
80-
h.separate = remove_brick
79+
space.set_collision_callback(
80+
collision_types["brick"], collision_types["ball"], separate=remove_brick
81+
)
8182

8283

8384
def main():
@@ -114,11 +115,10 @@ def main():
114115
def remove_first(arbiter, space, data):
115116
ball_shape = arbiter.shapes[0]
116117
space.remove(ball_shape, ball_shape.body)
117-
return True
118118

119-
h = space.add_collision_handler(collision_types["ball"], collision_types["bottom"])
120-
h.begin = remove_first
121-
space.add(bottom)
119+
space.set_collision_callback(
120+
collision_types["ball"], collision_types["bottom"], begin=remove_first
121+
)
122122

123123
### Player ship
124124
player_body = pymunk.Body(500, float("inf"))
@@ -142,10 +142,10 @@ def pre_solve(arbiter, space, data):
142142
set_.normal = normal
143143
set_.points[0].distance = 0
144144
arbiter.contact_point_set = set_
145-
return True
146145

147-
h = space.add_collision_handler(collision_types["player"], collision_types["ball"])
148-
h.pre_solve = pre_solve
146+
space.set_collision_callback(
147+
collision_types["player"], collision_types["ball"], pre_solve=pre_solve
148+
)
149149

150150
# restrict movement of player to a straigt line
151151
move_joint = pymunk.GrooveJoint(

pymunk/examples/collisions.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
"""This example attempts to display collision points, and the callbacks
2-
"""
1+
"""This example attempts to display collision points, and the callbacks"""
32

3+
import functools
44
import math
55
import random
66
import sys
@@ -20,8 +20,6 @@ def begin(arbiter, space, data):
2020
"separate": 0,
2121
}
2222

23-
return True
24-
2523

2624
def pre_solve(arbiter: pymunk.Arbiter, space, data):
2725
data["log"]["pre_solve"] += 1
@@ -54,8 +52,6 @@ def pre_solve(arbiter: pymunk.Arbiter, space, data):
5452
(p.point_a.interpolate_to(p.point_b, 0.5)),
5553
)
5654

57-
return True
58-
5955

6056
def post_solve(arbiter, space, data):
6157
# Will not be called, since the shapes are kinematic sensors
@@ -64,7 +60,6 @@ def post_solve(arbiter, space, data):
6460

6561
def separate(arbiter, space, data):
6662
data["log"]["separate"] += 1
67-
pass
6863

6964

7065
def main():
@@ -113,14 +108,19 @@ def main():
113108
selected_shape_idx = 0
114109
space.add(shapes[selected_shape_idx])
115110

116-
h = space.add_collision_handler(0, 1)
117-
h.data["screen"] = screen
118-
h.data["log"] = {"begin": 0, "pre_solve": 0, "post_solve": 0, "separate": 0}
119-
h.data["font"] = font
120-
h.begin = begin
121-
h.pre_solve = pre_solve
122-
h.post_solve = post_solve
123-
h.separate = separate
111+
data = {}
112+
h = space.set_collision_callback(
113+
0,
114+
1,
115+
begin=begin,
116+
pre_solve=pre_solve,
117+
post_solve=post_solve,
118+
separate=separate,
119+
data=data,
120+
)
121+
data["screen"] = screen
122+
data["log"] = {"begin": 0, "pre_solve": 0, "post_solve": 0, "separate": 0}
123+
data["font"] = font
124124

125125
while True:
126126
for event in pygame.event.get():
@@ -155,10 +155,10 @@ def main():
155155
)
156156

157157
y = 30
158-
for k in h.data["log"]:
158+
for k in data["log"]:
159159
screen.blit(
160160
font.render(
161-
f"{k}: {h.data['log'][k]}",
161+
f"{k}: {data['log'][k]}",
162162
True,
163163
pygame.Color("black"),
164164
),

0 commit comments

Comments
 (0)