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