1
1
__docformat__ = "reStructuredText"
2
2
3
+ import weakref
3
4
from typing import ( # Literal,
4
5
TYPE_CHECKING ,
5
6
Any ,
@@ -106,12 +107,13 @@ class Body(PickleMixin, TypingAttrMixing, object):
106
107
"is_sleeping" ,
107
108
"_velocity_func" ,
108
109
"_position_func" ,
110
+ # "_space",
109
111
]
110
112
111
113
_position_func : Optional [_PositionFunc ] = None
112
114
_velocity_func : Optional [_VelocityFunc ] = None
113
115
114
- _id_counter = 1
116
+ _dead_ref = weakref . ref ( set ())
115
117
116
118
def __init__ (
117
119
self , mass : float = 0 , moment : float = 0 , body_type : _BodyType = DYNAMIC
@@ -217,9 +219,7 @@ def freebody(cp_body: ffi.CData) -> None:
217
219
elif body_type == Body .STATIC :
218
220
self ._body = ffi .gc (lib .cpBodyNewStatic (), freebody )
219
221
220
- self ._space : Optional ["Space" ] = (
221
- None # Weak ref to the space holding this body (if any)
222
- )
222
+ self ._space : weakref .ref = Body ._dead_ref
223
223
224
224
self ._constraints : WeakSet ["Constraint" ] = (
225
225
WeakSet ()
@@ -264,7 +264,7 @@ def mass(self) -> float:
264
264
@mass .setter
265
265
def mass (self , mass : float ) -> None :
266
266
assert (
267
- self ._space is None or mass > 0
267
+ self .space is None or mass > 0
268
268
), "Dynamic bodies must have mass > 0 if they are attached to a Space."
269
269
lib .cpBodySetMass (self ._body , mass )
270
270
@@ -400,16 +400,14 @@ def rotation_vector(self) -> Vec2d:
400
400
def space (self ) -> Optional ["Space" ]:
401
401
"""Get the :py:class:`Space` that the body has been added to (or
402
402
None)."""
403
- assert hasattr (self , "_space" ), ( # TODO: When can this happen?
403
+ # This assert is tested in test_pickle_circular_ref
404
+ assert hasattr (self , "_space" ), (
404
405
"_space not set. This can mean there's a direct or indirect"
405
406
" circular reference between the Body and the Space. Circular"
406
407
" references are not supported when using pickle or copy and"
407
408
" might crash."
408
409
)
409
- if self ._space is not None :
410
- return self ._space ._get_self () # ugly hack because of weakref
411
- else :
412
- return None
410
+ return self ._space ()
413
411
414
412
def _set_velocity_func (self , func : _VelocityFunc ) -> None :
415
413
if func == Body .update_velocity :
@@ -571,7 +569,7 @@ def sleep(self) -> None:
571
569
572
570
Cannot be called from a callback.
573
571
"""
574
- if self ._space == None :
572
+ if self .space == None :
575
573
raise Exception ("Body not added to space" )
576
574
lib .cpBodySleep (self ._body )
577
575
@@ -589,7 +587,7 @@ def sleep_with_group(self, body: "Body") -> None:
589
587
to initialize levels and start stacks of objects in a pre-sleeping
590
588
state.
591
589
"""
592
- if self ._space == None :
590
+ if self .space == None :
593
591
raise Exception ("Body not added to space" )
594
592
lib .cpBodySleepWithGroup (self ._body , body ._body )
595
593
0 commit comments