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 /* ---- miscellaneous classes ---- */ 22 /**** Color ****/ 23 %extend b2Color { 24 public: b2Color(b2Color & other)25 b2Color(b2Color& other) { 26 return new b2Color(other.r, other.g, other.b); 27 } __get_bytes()28 PyObject* __get_bytes() { 29 PyObject* ret=PyList_New(3); 30 PyList_SetItem(ret, 0, SWIG_From_int((int)(255*$self->r))); 31 PyList_SetItem(ret, 1, SWIG_From_int((int)(255*$self->g))); 32 PyList_SetItem(ret, 2, SWIG_From_int((int)(255*$self->b))); 33 return ret; 34 } 35 36 %pythoncode %{ 37 __iter__ = lambda self: iter((self.r, self.g, self.b)) 38 __eq__ = lambda self, other: self.__equ(other) 39 __ne__ = lambda self,other: not self.__equ(other) 40 def __repr__(self): 41 return "b2Color(%g,%g,%g)" % (self.r, self.g, self.b) 42 def __len__(self): 43 return 3 44 def __copy__(self): 45 return b2Color(self.r, self.g, self.b) 46 def copy(self): 47 return b2Color(self.r, self.g, self.b) 48 def __set_bytes(self, value): 49 if len(value) != 3: 50 raise ValueError('Expected length 3 list') 51 self.r, self.g, self.b = value[0]/255, value[1]/255, value[2]/255 52 def __set_tuple(self, value): 53 if len(value) != 3: 54 raise ValueError('Expected length 3 list') 55 self.r, self.g, self.b = value[0], value[1], value[2] 56 def __nonzero__(self): 57 return self.r!=0.0 or self.g!=0.0 or self.b!=0.0 58 59 list = property(lambda self: list(self), __set_tuple) 60 bytes = property(__get_bytes, __set_bytes) 61 %} 62 63 float32 __getitem__(int i) { 64 if (i==0) 65 return $self->r; 66 else if (i==1) 67 return $self->g; 68 else if (i==2) 69 return $self->b; 70 71 PyErr_SetString(PyExc_IndexError, "Index must be in (0,1,2)"); 72 return 0.0f; 73 } 74 void __setitem__(int i, float32 value) { 75 if (i==0) 76 $self->r=value; 77 else if (i==1) 78 $self->g=value; 79 else if (i==2) 80 $self->b=value; 81 else 82 PyErr_SetString(PyExc_IndexError, "Index must be in (0,1,2)"); 83 } 84 b2Color __truediv__(float32 a) { 85 return b2Color($self->r / a, $self->g / a, $self->b / a); 86 } 87 b2Color __add__(b2Color& o) { 88 return b2Color($self->r + o.r, $self->g + o.g, $self->b + o.b); 89 } 90 b2Color __sub__(b2Color& o) { 91 return b2Color($self->r - o.r, $self->g - o.g, $self->b - o.b); 92 } 93 b2Color __div__(float32 a) { 94 return b2Color($self->r / a, $self->g / a, $self->b / a); 95 } 96 b2Color __rmul__(float32 a) { 97 return b2Color($self->r * a, $self->g * a, $self->b * a); 98 } 99 b2Color __mul__(float32 a) { 100 return b2Color($self->r * a, $self->g * a, $self->b * a); 101 } 102 void __isub(b2Color& o) { 103 $self->r -= o.r; 104 $self->g -= o.g; 105 $self->b -= o.b; 106 } 107 void __itruediv(b2Color& o) { 108 $self->r /= o.r; 109 $self->g /= o.g; 110 $self->b /= o.b; 111 } 112 void __idiv(b2Color& o) { 113 $self->r /= o.r; 114 $self->g /= o.g; 115 $self->b /= o.b; 116 } 117 void __imul(b2Color& o) { 118 $self->r *= o.r; 119 $self->g *= o.g; 120 $self->b *= o.b; 121 } 122 void __iadd(b2Color& o) { 123 $self->r += o.r; 124 $self->g += o.g; 125 $self->b += o.b; 126 } 127 bool __equ(b2Color& b) { 128 return ($self->r == b.r && $self->g==b.g && $self->b==b.b); 129 } 130 131 } 132 133 %feature("shadow") b2Color::__iadd { 134 def __iadd__(self, other): 135 self.__iadd(other) 136 return self 137 } 138 %feature("shadow") b2Color::__isub { 139 def __isub__(self, other): 140 self.__isub(other) 141 return self 142 } 143 %feature("shadow") b2Color::__imul { 144 def __imul__(self, other): 145 self.__imul(other) 146 return self 147 } 148 %feature("shadow") b2Color::__idiv { 149 def __idiv__(self, other): 150 self.__idiv(other) 151 return self 152 } 153 %feature("shadow") b2Color::__itruediv { 154 def __itruediv__(self, other): 155 self.__itruediv(other) 156 return self 157 } 158 159 160 /**** DistanceProxy ****/ 161 %extend b2DistanceProxy { 162 public: 163 %pythoncode %{ 164 def __get_vertices(self): 165 """Returns all of the vertices as a list of tuples [ (x1,y1), (x2,y2) ... (xN,yN) ]""" 166 return [ (self.__get_vertex(i).x, self.__get_vertex(i).y ) 167 for i in range(0, self.__get_vertex_count())] 168 vertices = property(__get_vertices, None) 169 %} 170 } 171 172 %feature("shadow") b2DistanceProxy::b2DistanceProxy() { 173 def __init__(self, shape, index=0): 174 _Box2D.b2DistanceProxy_swiginit(self,_Box2D.new_b2DistanceProxy()) 175 self.Set(shape, index) 176 } 177 178 /* Shouldn't need access to these, only by setting the shape. */ 179 %rename (__get_vertex) b2DistanceProxy::GetVertex; 180 %rename (__get_vertex_count) b2DistanceProxy::GetVertexCount; 181 %ignore b2DistanceProxy::m_count; 182 %ignore b2DistanceProxy::m_vertices; 183 %ignore b2DistanceProxy::m_radius; 184 185 /**** Version ****/ 186 %extend b2Version { 187 public: 188 %pythoncode %{ 189 def __repr__(self): 190 return "b2Version(%s.%s.%s)" % (self.major, self.minor, self.revision) 191 %} 192 } 193 194 /*** Replace b2Distance ***/ 195 %inline %{ 196 b2DistanceOutput* _b2Distance(b2Shape* shapeA, int idxA, b2Shape* shapeB, int idxB, b2Transform& transformA, b2Transform& transformB, bool useRadii=true) { 197 if (!shapeA || !shapeB) 198 return NULL; 199 200 b2DistanceInput input; 201 b2DistanceOutput* out=new b2DistanceOutput; 202 b2SimplexCache cache; 203 204 input.proxyA.Set(shapeA, idxA); 205 input.proxyB.Set(shapeB, idxB); 206 input.transformA = transformA; 207 input.transformB = transformB; 208 input.useRadii = useRadii; 209 210 cache.count=0; 211 b2Distance(out, &cache, &input); 212 return out; 213 } 214 b2DistanceOutput* _b2Distance(b2DistanceInput* input) { 215 if (!input) 216 return NULL; 217 218 b2DistanceOutput* out=new b2DistanceOutput; 219 b2SimplexCache cache; 220 cache.count=0; 221 b2Distance(out, &cache, input); 222 return out; 223 } 224 %} 225 226 %pythoncode %{ 227 import collections 228 229 b2DistanceResult = collections.namedtuple('b2DistanceResult', 230 'pointA pointB distance iterations') 231 232 def b2Distance(shapeA=None, idxA=0, shapeB=None, idxB=0, transformA=None, transformB=None, useRadii=True): 233 """ 234 Compute the closest points between two shapes. 235 236 Can be called one of two ways: 237 + b2Distance(b2DistanceInput) 238 This uses the b2DistanceInput structure, where you define your own 239 distance proxies 240 241 Or more conveniently using kwargs: 242 + b2Distance(shapeA=.., idxA=0, shapeB=.., idxB=0, transformA=.., 243 transformB=.., useRadii=True) 244 245 Returns a namedtuple in the form: 246 b2DistanceResult(pointA=(ax, ay), pointB=(bx, by), distance, 247 iterations) 248 """ 249 if isinstance(shapeA, b2DistanceInput): 250 out = _b2Distance(shapeA) 251 else: 252 out = _b2Distance(shapeA, idxA, shapeB, idxB, transformA, transformB, useRadii) 253 254 return b2DistanceResult(pointA=tuple(out.pointA), 255 pointB=tuple(out.pointB), 256 distance=out.distance, 257 iterations=out.iterations) 258 %} 259 260 %newobject _b2Distance; 261 %ignore b2Distance; 262 263 /**** Sweep ****/ 264 %extend b2Sweep { 265 public: 266 b2Transform* GetTransform(float32 alpha) { 267 b2Transform* out=new b2Transform; 268 $self->GetTransform(out, alpha); 269 return out; 270 } 271 } 272 273 %newobject b2Sweep::GetTransform; 274 275 /**** BroadPhase ****/ 276 //TODO: this needs to be fixed up 277 %extend b2BroadPhase { 278 public: 279 %pythoncode %{ 280 proxyCount=property(__GetProxyCount, None) 281 treeHeight=property(__GetTreeHeight, None) 282 treeBalance=property(__GetTreeBalance, None) 283 treeQuality=property(__GetTreeQuality, None) 284 %} 285 } 286 287 %rename (__GetProxyCount) b2BroadPhase::GetProxyCount; 288 %rename (__GetTreeHeight) b2BroadPhase::GetTreeHeight; 289 %rename (__GetTreeBalance) b2BroadPhase::GetTreeBalance; 290 %rename (__GetTreeQuality) b2BroadPhase::GetTreeQuality; 291 %ignore b2BroadPhase::GetUserData; 292 %ignore b2BroadPhase::CreateProxy; 293 %ignore b2BroadPhase::DestroyProxy; 294