1
1
__docformat__ = "reStructuredText"
2
2
3
- from typing import TYPE_CHECKING , Any , Callable , Dict , Optional
3
+ from typing import TYPE_CHECKING , Any , Callable , Dict
4
4
5
5
if TYPE_CHECKING :
6
6
from .space import Space
7
7
8
8
from ._chipmunk_cffi import ffi , lib
9
9
from .arbiter import Arbiter
10
10
11
- _CollisionCallbackBool = Callable [[Arbiter , "Space" , Any ], bool ]
12
- _CollisionCallbackNoReturn = Callable [[Arbiter , "Space" , Any ], None ]
11
+ _CollisionCallbackBool = Callable [[Arbiter , "Space" , Dict [ Any , Any ] ], bool ]
12
+ _CollisionCallbackNoReturn = Callable [[Arbiter , "Space" , Dict [ Any , Any ] ], None ]
13
13
14
14
15
15
class CollisionHandler (object ):
@@ -42,25 +42,13 @@ def __init__(self, _handler: Any, space: "Space") -> None:
42
42
self ._handler .userData = self ._userData
43
43
44
44
self ._space = space
45
- self ._begin : Optional [ _CollisionCallbackBool ] = None
46
- self ._pre_solve : Optional [ _CollisionCallbackBool ] = None
47
- self ._post_solve : Optional [ _CollisionCallbackNoReturn ] = None
48
- self ._separate : Optional [ _CollisionCallbackNoReturn ] = None
45
+ self ._begin : _CollisionCallbackBool = CollisionHandler . always_collide
46
+ self ._pre_solve : _CollisionCallbackBool = CollisionHandler . always_collide
47
+ self ._post_solve : _CollisionCallbackNoReturn = CollisionHandler . do_nothing
48
+ self ._separate : _CollisionCallbackNoReturn = CollisionHandler . do_nothing
49
49
50
50
self ._data : Dict [Any , Any ] = {}
51
51
52
- def _reset (self ) -> None :
53
- def allways_collide (arb : Arbiter , space : "Space" , data : Any ) -> bool :
54
- return True
55
-
56
- def do_nothing (arb : Arbiter , space : "Space" , data : Any ) -> None :
57
- return
58
-
59
- self .begin = allways_collide
60
- self .pre_solve = allways_collide
61
- self .post_solve = do_nothing
62
- self .separate = do_nothing
63
-
64
52
@property
65
53
def data (self ) -> Dict [Any , Any ]:
66
54
"""Data property that get passed on into the
@@ -72,17 +60,9 @@ def data(self) -> Dict[Any, Any]:
72
60
"""
73
61
return self ._data
74
62
75
- def _set_begin (self , func : _CollisionCallbackBool ) -> None :
76
- self ._begin = func
77
- self ._handler .beginFunc = lib .ext_cpCollisionBeginFunc
78
-
79
- def _get_begin (self ) -> Optional [_CollisionCallbackBool ]:
80
- return self ._begin
81
-
82
- begin = property (
83
- _get_begin ,
84
- _set_begin ,
85
- doc = """Two shapes just started touching for the first time this step.
63
+ @property
64
+ def begin (self ) -> _CollisionCallbackBool :
65
+ """Two shapes just started touching for the first time this step.
86
66
87
67
``func(arbiter, space, data) -> bool``
88
68
@@ -91,20 +71,24 @@ def _get_begin(self) -> Optional[_CollisionCallbackBool]:
91
71
false, the `pre_solve` and `post_solve` callbacks will never be run,
92
72
but you will still recieve a separate event when the shapes stop
93
73
overlapping.
94
- """ ,
95
- )
74
+ """
75
+ return self . _begin
96
76
97
- def _set_pre_solve (self , func : _CollisionCallbackBool ) -> None :
98
- self ._pre_solve = func
99
- self ._handler .preSolveFunc = lib .ext_cpCollisionPreSolveFunc
77
+ @begin .setter
78
+ def begin (self , func : _CollisionCallbackBool ) -> None :
79
+ assert (
80
+ func is not None
81
+ ), "To reset the begin callback, set handler.begin = CollisionHandler.always_collide"
82
+ self ._begin = func
100
83
101
- def _get_pre_solve (self ) -> Optional [_CollisionCallbackBool ]:
102
- return self ._pre_solve
84
+ if self ._begin == CollisionHandler .always_collide :
85
+ self ._handler .beginFunc = ffi .addressof (lib , "AlwaysCollide" )
86
+ else :
87
+ self ._handler .beginFunc = lib .ext_cpCollisionBeginFunc
103
88
104
- pre_solve = property (
105
- _get_pre_solve ,
106
- _set_pre_solve ,
107
- doc = """Two shapes are touching during this step.
89
+ @property
90
+ def pre_solve (self ) -> _CollisionCallbackBool :
91
+ """Two shapes are touching during this step.
108
92
109
93
``func(arbiter, space, data) -> bool``
110
94
@@ -113,48 +97,90 @@ def _get_pre_solve(self) -> Optional[_CollisionCallbackBool]:
113
97
override collision values using Arbiter.friction, Arbiter.elasticity
114
98
or Arbiter.surfaceVelocity to provide custom friction, elasticity,
115
99
or surface velocity values. See Arbiter for more info.
116
- """ ,
117
- )
118
-
119
- def _set_post_solve (self , func : _CollisionCallbackNoReturn ) -> None :
100
+ """
101
+ return self ._pre_solve
120
102
121
- self ._post_solve = func
122
- self ._handler .postSolveFunc = lib .ext_cpCollisionPostSolveFunc
103
+ @pre_solve .setter
104
+ def pre_solve (self , func : _CollisionCallbackBool ) -> None :
105
+ assert (
106
+ func is not None
107
+ ), "To reset the pre_solve callback, set handler.pre_solve = CollisionHandler.always_collide"
108
+ self ._pre_solve = func
123
109
124
- def _get_post_solve (self ) -> Optional [_CollisionCallbackNoReturn ]:
125
- return self ._post_solve
110
+ if self ._pre_solve == CollisionHandler .always_collide :
111
+ self ._handler .preSolveFunc = ffi .addressof (lib , "AlwaysCollide" )
112
+ else :
113
+ self ._handler .preSolveFunc = lib .ext_cpCollisionPreSolveFunc
126
114
127
- post_solve = property (
128
- _get_post_solve ,
129
- _set_post_solve ,
130
- doc = """Two shapes are touching and their collision response has been
115
+ @property
116
+ def post_solve (self ) -> _CollisionCallbackNoReturn :
117
+ """Two shapes are touching and their collision response has been
131
118
processed.
132
119
133
120
``func(arbiter, space, data)``
134
121
135
122
You can retrieve the collision impulse or kinetic energy at this
136
123
time if you want to use it to calculate sound volumes or damage
137
124
amounts. See Arbiter for more info.
138
- """ ,
139
- )
125
+ """
126
+ return self . _post_solve
140
127
141
- def _set_separate (self , func : _CollisionCallbackNoReturn ) -> None :
142
- self ._separate = func
143
- self ._handler .separateFunc = lib .ext_cpCollisionSeparateFunc
128
+ @post_solve .setter
129
+ def post_solve (self , func : _CollisionCallbackNoReturn ) -> None :
130
+ assert (
131
+ func is not None
132
+ ), "To reset the post_solve callback, set handler.post_solve = CollisionHandler.do_nothing"
133
+ self ._post_solve = func
144
134
145
- def _get_separate (self ) -> Optional [_CollisionCallbackNoReturn ]:
146
- return self ._separate
135
+ if self ._post_solve == CollisionHandler .do_nothing :
136
+ self ._handler .postSolveFunc = ffi .addressof (lib , "DoNothing" )
137
+ else :
138
+ self ._handler .postSolveFunc = lib .ext_cpCollisionPostSolveFunc
147
139
148
- separate = property (
149
- _get_separate ,
150
- _set_separate ,
151
- doc = """Two shapes have just stopped touching for the first time this
140
+ self ._handler .postSolveFunc = lib .ext_cpCollisionPostSolveFunc
141
+
142
+ @property
143
+ def separate (self ) -> _CollisionCallbackNoReturn :
144
+ """Two shapes have just stopped touching for the first time this
152
145
step.
153
146
154
147
``func(arbiter, space, data)``
155
148
156
149
To ensure that begin()/separate() are always called in balanced
157
150
pairs, it will also be called when removing a shape while its in
158
151
contact with something or when de-allocating the space.
159
- """ ,
160
- )
152
+ """
153
+ return self ._separate
154
+
155
+ @separate .setter
156
+ def separate (self , func : _CollisionCallbackNoReturn ) -> None :
157
+ assert (
158
+ func is not None
159
+ ), "To reset the separate callback, set handler.separate = CollisionHandler.do_nothing"
160
+ self ._separate = func
161
+
162
+ if self ._separate == CollisionHandler .do_nothing :
163
+ self ._handler .separateFunc = ffi .addressof (lib , "DoNothing" )
164
+ else :
165
+ self ._handler .separateFunc = lib .ext_cpCollisionSeparateFunc
166
+
167
+ @staticmethod
168
+ def do_nothing (arbiter : Arbiter , space : "Space" , data : Dict [Any , Any ]) -> None :
169
+ """The default do nothing method used for the post_solve and seprate
170
+ callbacks.
171
+
172
+ Note that its more efficient to set this method than to define your own
173
+ do nothing method.
174
+ """
175
+ return
176
+
177
+ @staticmethod
178
+ def always_collide (arbiter : Arbiter , space : "Space" , data : Dict [Any , Any ]) -> bool :
179
+ """The default method used for the begin and pre_solve callbacks.
180
+
181
+ It will always return True, meaning the collision should not be ignored.
182
+
183
+ Note that its more efficient to set this method than to define your own
184
+ return True method.
185
+ """
186
+ return True
0 commit comments