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