1 /*
2 * pybox2d -- http://pybox2d.googlecode.com
3 *
4 * Copyright (c) 2010 Ken Lauer / sirkne at gmail dot com
5 *
6 * This software is provided 'as-is', without any express or implied
7 * warranty.  In no event will the authors be held liable for any damages
8 * arising from the use of this software.
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 */
20 
21 // i /really/ did not understand kwargs, apparently...
22 %feature("shadow") b2World::b2World(const b2Vec2& gravity) {
23     def __init__(self, gravity=(0, -10), doSleep=True, **kwargs):
24         """__init__(self, gravity=(0, -10), doSleep=True, **kwargs) -> b2World
25 
26         Additional kwargs like contactListener will be passed after the world is created.
27 
28         Examples:
29          b2World(gravity=(0,-10), doSleep=True)
30          b2World(contactListener=myListener)
31         """
32         _Box2D.b2World_swiginit(self,_Box2D.new_b2World(gravity))
33 
34         self.allowSleeping = doSleep
35 
36         for key, value in kwargs.items():
37             try:
38                 setattr(self, key, value)
39             except Exception as ex:
40                 raise ex.__class__('Failed on kwargs, class="%s" key="%s": %s' \
41                             % (self.__class__.__name__, key, ex))
42 }
43 
44 %extend b2World {
45 public:
46     %pythoncode %{
47         def __iter__(self):
48             """
49             Iterates over the bodies in the world
50             """
51             for body in self.bodies:
52                 yield body
53 
54         def CreateDynamicBody(self, **kwargs):
55             """
56             Create a single dynamic body in the world.
57 
58             Accepts only kwargs to a b2BodyDef. For more information, see
59             CreateBody and b2BodyDef.
60             """
61             kwargs['type'] = b2_dynamicBody
62             return self.CreateBody(**kwargs)
63 
64         def CreateKinematicBody(self, **kwargs):
65             """
66             Create a single kinematic body in the world.
67 
68             Accepts only kwargs to a b2BodyDef. For more information, see
69             CreateBody and b2BodyDef.
70             """
71             kwargs['type'] = b2_kinematicBody
72             return self.CreateBody(**kwargs)
73 
74         def CreateStaticBody(self, **kwargs):
75             """
76             Create a single static body in the world.
77 
78             Accepts only kwargs to a b2BodyDef. For more information, see
79             CreateBody and b2BodyDef.
80             """
81             kwargs['type'] = b2_staticBody
82             return self.CreateBody(**kwargs)
83 
84         def CreateBody(self, defn=None, **kwargs):
85             """
86             Create a body in the world.
87             Takes a single b2BodyDef argument, or kwargs to pass to a temporary b2BodyDef.
88             world.CreateBody(position=(1,2), angle=1)
89             is short for:
90             world.CreateBody(b2BodyDef(position=(1,2), angle=1))
91 
92             If the definition (or kwargs) sets 'fixtures', they will be created on the
93             newly created body. A single fixture is also accepted.
94 
95             CreateBody(..., fixtures=[])
96 
97             This is short for:
98                 body = CreateBody(...)
99                 for fixture in []:
100                     body.CreateFixture(fixture)
101 
102              'shapes' and 'shapeFixture' are also accepted:
103              CreateBody(..., shapes=[], shapeFixture=b2FixtureDef())
104 
105             This is short for:
106                 body = CreateBody(...)
107                 body.CreateFixturesFromShapes(shapes=[], shapeFixture=b2FixtureDef())
108             """
109             if defn is not None:
110                 if not isinstance(defn, b2BodyDef):
111                     raise TypeError('Expected b2BodyDef')
112             else:
113                 defn = b2BodyDef(**kwargs)
114 
115             body=self.__CreateBody(defn)
116 
117             if defn.fixtures:
118                 if isinstance(defn.fixtures, (list, tuple)):
119                     for fixture in defn.fixtures:
120                         body.CreateFixture(fixture)
121                 else:
122                     body.CreateFixture(defn.fixtures)
123             if defn.shapes:
124                 body.CreateFixturesFromShapes(shapes=defn.shapes, shapeFixture=defn.shapeFixture)
125 
126             if 'massData' in kwargs:
127                 body.massData=kwargs['massData']
128             if 'localCenter' in kwargs:
129                 body.localCenter=kwargs['localCenter']
130             if 'inertia' in kwargs:
131                 body.inertia=kwargs['inertia']
132             if 'mass' in kwargs:
133                 body.mass=kwargs['mass']
134 
135             return body
136 
137         def CreateDistanceJoint(self, **kwargs):
138             """
139             Create a single b2DistanceJoint. Only accepts kwargs to the joint definition.
140 
141             Raises ValueError if either bodyA or bodyB is left unset.
142             """
143             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
144                 raise ValueError('Requires at least bodyA and bodyB be set')
145             return self.__CreateJoint(b2DistanceJointDef(**kwargs))
146 
147         def CreateRopeJoint(self, **kwargs):
148             """
149             Create a single b2RopeJoint. Only accepts kwargs to the joint definition.
150 
151             Raises ValueError if either bodyA or bodyB is left unset.
152             """
153             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
154                 raise ValueError('Requires at least bodyA and bodyB be set')
155             return self.__CreateJoint(b2RopeJointDef(**kwargs))
156 
157         def CreateFrictionJoint(self, **kwargs):
158             """
159             Create a single b2FrictionJoint. Only accepts kwargs to the joint definition.
160 
161             Raises ValueError if either bodyA or bodyB is left unset.
162             """
163             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
164                 raise ValueError('Requires at least bodyA and bodyB be set')
165             return self.__CreateJoint(b2FrictionJointDef(**kwargs))
166 
167         def CreateGearJoint(self, **kwargs):
168             """
169             Create a single b2GearJoint. Only accepts kwargs to the joint definition.
170 
171             Raises ValueError if either joint1 or joint2 is left unset.
172             """
173             if 'joint1' not in kwargs or 'joint2' not in kwargs:
174                 raise ValueError('Gear joint requires that both joint1 and joint2 be set')
175             return self.__CreateJoint(b2GearJointDef(**kwargs))
176 
177         def CreateWheelJoint(self, **kwargs):
178             """
179             Create a single b2WheelJoint. Only accepts kwargs to the joint definition.
180 
181             Raises ValueError if either bodyA or bodyB is left unset.
182             """
183             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
184                 raise ValueError('Requires at least bodyA and bodyB be set')
185             return self.__CreateJoint(b2WheelJointDef(**kwargs))
186 
187         def CreateMouseJoint(self, **kwargs):
188             """
189             Create a single b2MouseJoint. Only accepts kwargs to the joint definition.
190 
191             Raises ValueError if either bodyA or bodyB is left unset.
192             """
193             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
194                 raise ValueError('Requires at least bodyA and bodyB be set')
195             return self.__CreateJoint(b2MouseJointDef(**kwargs))
196 
197         def CreatePrismaticJoint(self, **kwargs):
198             """
199             Create a single b2PrismaticJoint. Only accepts kwargs to the joint definition.
200 
201             Raises ValueError if either bodyA or bodyB is left unset.
202             """
203             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
204                 raise ValueError('Requires at least bodyA and bodyB be set')
205             return self.__CreateJoint(b2PrismaticJointDef(**kwargs))
206 
207         def CreatePulleyJoint(self, **kwargs):
208             """
209             Create a single b2PulleyJoint. Only accepts kwargs to the joint definition.
210 
211             Raises ValueError if either bodyA or bodyB is left unset.
212             """
213             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
214                 raise ValueError('Requires at least bodyA and bodyB be set')
215             return self.__CreateJoint(b2PulleyJointDef(**kwargs))
216 
217         def CreateRevoluteJoint(self, **kwargs):
218             """
219             Create a single b2RevoluteJoint. Only accepts kwargs to the joint definition.
220 
221             Raises ValueError if either bodyA or bodyB is left unset.
222             """
223             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
224                 raise ValueError('Requires at least bodyA and bodyB be set')
225             return self.__CreateJoint(b2RevoluteJointDef(**kwargs))
226 
227         def CreateWeldJoint(self, **kwargs):
228             """
229             Create a single b2WeldJoint. Only accepts kwargs to the joint definition.
230 
231             Raises ValueError if either bodyA or bodyB is left unset.
232             """
233             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
234                 raise ValueError('Requires at least bodyA and bodyB be set')
235             return self.__CreateJoint(b2WeldJointDef(**kwargs))
236 
237         def CreateMotorJoint(self, **kwargs):
238             """
239             Create a single b2MotorJoint. Only accepts kwargs to the joint definition.
240 
241             Raises ValueError if either bodyA or bodyB is left unset.
242             """
243             if 'bodyA' not in kwargs or 'bodyB' not in kwargs:
244                 raise ValueError('Requires at least bodyA and bodyB be set')
245             return self.__CreateJoint(b2MotorJointDef(**kwargs))
246 
247         def CreateJoint(self, defn=None, type=None, **kwargs):
248             """
249             Create a joint in the world.
250             Takes a single b2JointDef argument, or kwargs to pass to a temporary b2JointDef.
251 
252             All of these are exactly equivalent:
253             world.CreateJoint(type=b2RevoluteJoint, bodyA=body, bodyB=body2)
254             world.CreateJoint(type=b2RevoluteJointDef, bodyA=body, bodyB=body2)
255             world.CreateJoint(b2RevoluteJointDef(bodyA=body, bodyB=body2))
256             """
257             if defn is not None:
258                 if not isinstance(defn, b2JointDef):
259                     raise TypeError('Expected b2JointDef')
260                 if defn.bodyA is None or defn.bodyB is None:
261                     raise ValueError('bodyA and bodyB must be set')
262             else:
263                 if type is not None:
264                     if issubclass(type, b2JointDef):
265                         class_type = type
266                     elif issubclass(type, b2Joint):  # a b2Joint passed in, so get the b2JointDef
267                         class_type = globals()[type.__name__ + 'Def']
268                     else:
269                         raise TypeError('Expected "type" to be a b2Joint or b2JointDef')
270                 else:
271                     raise TypeError('Expected "type" to be a b2Joint or b2JointDef')
272 
273                 defn = class_type(**kwargs)
274 
275             if isinstance(defn, b2GearJointDef):
276                 if not defn.joint1 or not defn.joint2:
277                     raise ValueError('Gear joint requires that both joint1 and joint2 be set')
278             else:
279                 if not defn.bodyA or not defn.bodyB:
280                     raise ValueError('Body or bodies not set (bodyA, bodyB)')
281 
282             return self.__CreateJoint(defn)
283 
284         # The logic behind these functions is that they increase the refcount
285         # of the listeners as you set them, so it is no longer necessary to keep
286         # a copy on your own. Upon destruction of the object, it should be cleared
287         # also clearing the refcount of the function.
288         # Now using it also to buffer previously write-only values in the shadowed
289         # class to make them read-write.
290         def __GetData(self, name):
291             if name in list(self.__data.keys()):
292                 return self.__data[name]
293             else:
294                 return None
295         def __SetData(self, name, value, fcn):
296             self.__data[name] = value
297             fcn(value)
298 
299         # Read-write properties
300         gravity   = property(__GetGravity, __SetGravity)
301         autoClearForces = property(__GetAutoClearForces, __SetAutoClearForces)
302         __data = {} # holds the listeners so they can be properly destroyed, and buffer other data
303         destructionListener = property(lambda self: self.__GetData('destruction'),
304                                        lambda self, fcn: self.__SetData('destruction', fcn, self.__SetDestructionListener_internal))
305         contactListener= property(lambda self: self.__GetData('contact'),
306                                   lambda self, fcn: self.__SetData('contact', fcn, self.__SetContactListener_internal))
307         contactFilter= property(lambda self: self.__GetData('contactfilter'),
308                                 lambda self, fcn: self.__SetData('contactfilter', fcn, self.__SetContactFilter_internal))
309         renderer= property(lambda self: self.__GetData('renderer'),
310                             lambda self, fcn: self.__SetData('renderer', fcn, self.__SetDebugDraw_internal))
311 
312         continuousPhysics = property(__GetContinuousPhysics, __SetContinuousPhysics)
313         warmStarting = property(__GetWarmStarting, __SetWarmStarting)
314         subStepping = property(__GetSubStepping, __SetSubStepping)
315 
316         # Read-only
317         contactManager= property(__GetContactManager, None)
318         contactCount  = property(__GetContactCount, None)
319         bodyCount     = property(__GetBodyCount, None)
320         jointCount    = property(__GetJointCount, None)
321         proxyCount    = property(__GetProxyCount, None)
322         joints  = property(lambda self: _list_from_linked_list(self.__GetJointList_internal()), None,
323                             doc="""All joints in the world.  NOTE: This re-creates the list on every call. See also joints_gen.""")
324         bodies  = property(lambda self: _list_from_linked_list(self.__GetBodyList_internal()), None,
325                             doc="""All bodies in the world.  NOTE: This re-creates the list on every call. See also bodies_gen.""")
326         contacts= property(lambda self: _list_from_linked_list(self.__GetContactList_internal()), None,
327                             doc="""All contacts in the world.  NOTE: This re-creates the list on every call. See also contacts_gen.""")
328         joints_gen = property(lambda self: _indexable_generator(_generator_from_linked_list(self.__GetJointList_internal())), None,
329                             doc="""Indexable generator of the connected joints to this body.
330                             NOTE: When not using the whole list, this may be preferable to using 'joints'.""")
331         bodies_gen = property(lambda self: _indexable_generator(_generator_from_linked_list(self.__GetBodyList_internal())), None,
332                             doc="""Indexable generator of all bodies.
333                             NOTE: When not using the whole list, this may be preferable to using 'bodies'.""")
334         contacts_gen = property(lambda self: _indexable_generator(_generator_from_linked_list(self.__GetContactList_internal())), None,
335                             doc="""Indexable generator of all contacts.
336                             NOTE: When not using the whole list, this may be preferable to using 'contacts'.""")
337         locked  = property(__IsLocked, None)
338 
339     %}
340 }
341 
342 %rename (__GetGravity) b2World::GetGravity;
343 %rename (__SetGravity) b2World::SetGravity;
344 %rename (__GetJointList_internal) b2World::GetJointList;
345 %rename (__GetJointCount) b2World::GetJointCount;
346 %rename (__GetBodyList_internal) b2World::GetBodyList;
347 %rename (__GetContactList_internal) b2World::GetContactList;
348 %rename (__SetDestructionListener_internal) b2World::SetDestructionListener;
349 %rename (__SetContactFilter_internal) b2World::SetContactFilter;
350 %rename (__SetContactListener_internal) b2World::SetContactListener;
351 %rename (__SetDebugDraw_internal) b2World::SetDebugDraw;
352 %rename (__GetContactCount) b2World::GetContactCount;
353 %rename (__GetProxyCount) b2World::GetProxyCount;
354 %rename (__GetBodyCount) b2World::GetBodyCount;
355 %rename (__IsLocked) b2World::IsLocked;
356 %rename (__SetContinuousPhysics_internal) b2World::SetContinuousPhysics;
357 %rename (__SetWarmStarting_internal) b2World::SetWarmStarting;
358 %rename (__SetSubStepping_internal) b2World::SetSubStepping;
359 %rename (__SetAutoClearForces) b2World::SetAutoClearForces;
360 %rename (__GetAutoClearForces) b2World::GetAutoClearForces;
361 %rename (__GetContactManager) b2World::GetContactManager;
362 
363 %rename (__GetContinuousPhysics) b2World::GetContinuousPhysics;
364 %rename (__SetContinuousPhysics) b2World::SetContinuousPhysics;
365 %rename (__GetWarmStarting) b2World::GetWarmStarting;
366 %rename (__SetWarmStarting) b2World::SetWarmStarting;
367 %rename (__GetSubStepping) b2World::GetSubStepping;
368 %rename (__SetSubStepping) b2World::SetSubStepping;
369