[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / third-party / chipmunk2d / objectivec / src / ChipmunkShape.m
1 /* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
2  * 
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  * 
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  * 
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19  * SOFTWARE.
20  */
21
22 #import "ObjectiveChipmunk/ObjectiveChipmunk.h"
23
24 @interface ChipmunkSpace(DoubleDispatch)
25
26 - (ChipmunkShape *)addShape:(ChipmunkShape *)obj;
27 - (ChipmunkShape *)removeShape:(ChipmunkShape *)obj;
28
29 @end
30
31 @implementation ChipmunkShape
32
33 @synthesize userData = _userData;
34
35 +(ChipmunkShape *)shapeFromCPShape:(cpShape *)shape
36 {
37         ChipmunkShape *obj = shape->userData;
38         cpAssertHard([obj isKindOfClass:[ChipmunkShape class]], "'shape->data' is not a pointer to a ChipmunkShape object.");
39         
40         return obj;
41 }
42
43 - (void) dealloc {
44         [self.body release];
45         cpShapeDestroy(self.shape);
46         [super dealloc];
47 }
48
49
50 - (cpShape *)shape {
51         [self doesNotRecognizeSelector:_cmd];
52         return nil;
53 }
54
55 - (ChipmunkBody *)body {
56         cpBody *body = cpShapeGetBody(self.shape);
57         return (body ? cpBodyGetUserData(body) : nil);
58 }
59
60 - (void)setBody:(ChipmunkBody *)body {
61         if(self.body != body){
62                 [self.body release];
63                 cpShapeSetBody(self.shape, [body retain].body);
64         }
65 }
66
67 -(cpFloat)mass {return cpShapeGetMass(self.shape);}
68 -(void)setMass:(cpFloat)mass {cpShapeSetMass(self.shape, mass);}
69
70 -(cpFloat)density {return cpShapeGetDensity(self.shape);}
71 -(void)setDensity:(cpFloat)density {cpShapeSetDensity(self.shape, density);}
72
73 -(cpFloat)moment {return cpShapeGetMoment(self.shape);}
74 -(cpFloat)area {return cpShapeGetArea(self.shape);}
75 -(cpVect)centerOfGravity {return cpShapeGetCenterOfGravity(self.shape);}
76
77 // accessor macros
78 #define getter(type, lower, upper) \
79 - (type)lower {return cpShapeGet##upper(self.shape);}
80 #define setter(type, lower, upper) \
81 - (void)set##upper:(type)value {cpShapeSet##upper(self.shape, value);};
82 #define both(type, lower, upper) \
83 getter(type, lower, upper) \
84 setter(type, lower, upper)
85
86 getter(cpBB, bb, BB)
87 both(BOOL, sensor, Sensor)
88 both(cpFloat, elasticity, Elasticity)
89 both(cpFloat, friction, Friction)
90 both(cpVect, surfaceVelocity, SurfaceVelocity)
91 both(cpCollisionType, collisionType, CollisionType)
92 both(cpShapeFilter, filter, Filter)
93
94 -(ChipmunkSpace *)space {
95         cpSpace *space = cpShapeGetSpace(self.shape);
96         return (ChipmunkSpace *)(space ? cpSpaceGetUserData(space) : nil);
97 }
98
99 - (cpBB)cacheBB {return cpShapeCacheBB(self.shape);}
100
101 - (ChipmunkPointQueryInfo *)pointQuery:(cpVect)point
102 {
103         cpPointQueryInfo info;
104         cpShapePointQuery(self.shape, point, &info);
105         return (info.shape ? [[[ChipmunkPointQueryInfo alloc] initWithInfo:&info] autorelease] : nil);
106 }
107
108 - (ChipmunkSegmentQueryInfo *)segmentQueryFrom:(cpVect)start to:(cpVect)end radius:(cpFloat)radius
109 {
110         cpSegmentQueryInfo info;
111         if(cpShapeSegmentQuery(self.shape, start, end, radius, &info)){
112                 return [[[ChipmunkSegmentQueryInfo alloc] initWithInfo:&info start:start end:end] autorelease];
113         } else {
114                 return nil;
115         }
116 }
117
118
119 - (NSArray *)chipmunkObjects {return [NSArray arrayWithObject:self];}
120 - (void)addToSpace:(ChipmunkSpace *)space {[space addShape:self];}
121 - (void)removeFromSpace:(ChipmunkSpace *)space {[space removeShape:self];}
122
123 @end
124
125
126 @implementation ChipmunkPointQueryInfo
127
128 - (id)initWithInfo:(cpPointQueryInfo *)info
129 {
130         if((self = [super init])){
131                 _info = (*info);
132                 [self.shape retain];
133         }
134         
135         return self;
136 }
137
138 - (cpPointQueryInfo *)info {return &_info;}
139 - (ChipmunkShape *)shape {return (_info.shape ? _info.shape->userData : nil);}
140 - (cpVect)point {return _info.point;}
141 - (cpFloat)distance {return _info.distance;}
142 - (cpVect)gradient {return _info.gradient;}
143
144 - (void)dealloc
145 {
146         [self.shape release];
147         [super dealloc];
148 }
149
150
151 @end
152
153
154 @implementation ChipmunkSegmentQueryInfo
155
156 - (id)initWithInfo:(cpSegmentQueryInfo *)info start:(cpVect)start end:(cpVect)end
157 {
158         if((self = [super init])){
159                 _info = (*info);
160                 _start = start;
161                 _end = end;
162                 
163                 [self.shape retain];
164         }
165         
166         return self;
167 }
168
169 - (cpSegmentQueryInfo *)info {return &_info;}
170 - (ChipmunkShape *)shape {return (_info.shape ? _info.shape->userData : nil);}
171 - (cpFloat)t {return _info.alpha;}
172 - (cpVect)normal {return _info.normal;}
173 - (cpVect)point {return _info.point;}
174 - (cpFloat)dist {return cpvdist(_start, _end)*_info.alpha;}
175 - (cpVect)start {return _start;}
176 - (cpVect)end {return _end;}
177
178 - (void)dealloc
179 {
180         [self.shape release];
181         [super dealloc];
182 }
183
184
185 @end
186
187
188 @implementation ChipmunkShapeQueryInfo
189
190 @synthesize shape = _shape;
191 - (cpContactPointSet *)contactPoints {return &_contactPoints;}
192
193 - (id)initWithShape:(ChipmunkShape *)shape andPoints:(cpContactPointSet *)set
194 {
195         if((self = [super init])){
196                 _shape = [shape retain];
197                 _contactPoints = *set;
198         }
199         
200         return self;
201 }
202
203 - (void)dealloc {
204         [_shape release];
205         [super dealloc];
206 }
207
208 @end
209
210 @implementation ChipmunkCircleShape {
211         cpCircleShape _shape;
212 }
213
214
215 + (ChipmunkCircleShape *)circleWithBody:(ChipmunkBody *)body radius:(cpFloat)radius offset:(cpVect)offset
216 {
217         return [[[self alloc] initWithBody:body radius:radius offset:offset] autorelease];
218 }
219
220 - (cpShape *)shape {return (cpShape *)&_shape;}
221
222 - (id)initWithBody:(ChipmunkBody *)body radius:(cpFloat)radius offset:(cpVect)offset {
223         if((self = [super init])){
224                 [body retain];
225                 cpCircleShapeInit(&_shape, body.body, radius, offset);
226                 self.shape->userData = self;
227         }
228         
229         return self;
230 }
231
232 - (cpFloat)radius {return cpCircleShapeGetRadius((cpShape *)&_shape);}
233 - (cpVect)offset {return cpCircleShapeGetOffset((cpShape *)&_shape);}
234
235 @end
236
237
238 @implementation ChipmunkSegmentShape {
239         cpSegmentShape _shape;
240 }
241
242 + (ChipmunkSegmentShape *)segmentWithBody:(ChipmunkBody *)body from:(cpVect)a to:(cpVect)b radius:(cpFloat)radius
243 {
244         return [[[self alloc] initWithBody:body from:a to:b radius:radius] autorelease];
245 }
246
247 - (cpShape *)shape {return (cpShape *)&_shape;}
248
249 - (id)initWithBody:(ChipmunkBody *)body from:(cpVect)a to:(cpVect)b radius:(cpFloat)radius {
250         if((self = [super init])){
251                 [body retain];
252                 cpSegmentShapeInit(&_shape, body.body, a, b, radius);
253                 self.shape->userData = self;
254         }
255         
256         return self;
257 }
258
259 - (void)setPrevNeighbor:(cpVect)prev nextNeighbor:(cpVect)next
260 {
261         cpSegmentShapeSetNeighbors((cpShape *)&_shape, prev, next);
262 }
263
264 - (cpVect)a {return cpSegmentShapeGetA((cpShape *)&_shape);}
265 - (cpVect)b {return cpSegmentShapeGetB((cpShape *)&_shape);}
266 - (cpVect)normal {return cpSegmentShapeGetNormal((cpShape *)&_shape);}
267 - (cpFloat)radius {return cpSegmentShapeGetRadius((cpShape *)&_shape);}
268
269 @end
270
271
272 @implementation ChipmunkPolyShape {
273         cpPolyShape _shape;
274 }
275
276 + (id)polyWithBody:(ChipmunkBody *)body count:(int)count verts:(const cpVect *)verts transform:(cpTransform)transform radius:(cpFloat)radius
277 {
278         return [[[self alloc] initWithBody:body count:count verts:verts transform:transform radius:radius] autorelease];
279 }
280
281 + (id)boxWithBody:(ChipmunkBody *)body width:(cpFloat)width height:(cpFloat)height radius:(cpFloat)radius
282 {
283         return [[[self alloc] initBoxWithBody:body width:width height:height radius:radius] autorelease];
284 }
285
286 + (id)boxWithBody:(ChipmunkBody *)body bb:(cpBB)bb radius:(cpFloat)radius
287 {
288         return [[[self alloc] initBoxWithBody:body bb:bb radius:radius] autorelease];
289 }
290
291 - (cpShape *)shape {return (cpShape *)&_shape;}
292
293 - (id)initWithBody:(ChipmunkBody *)body count:(int)count verts:(const cpVect *)verts transform:(cpTransform)transform radius:(cpFloat)radius
294 {
295         if((self = [super init])){
296                 [body retain];
297                 cpPolyShapeInit(&_shape, body.body, count, verts, transform, radius);
298                 self.shape->userData = self;
299         }
300         
301         return self;
302 }
303
304 - (id)initBoxWithBody:(ChipmunkBody *)body width:(cpFloat)width height:(cpFloat)height radius:(cpFloat)radius
305 {
306         if((self = [super init])){
307                 [body retain];
308                 cpBoxShapeInit(&_shape, body.body, width, height, radius);
309                 self.shape->userData = self;
310         }
311         
312         return self;
313 }
314
315 - (id)initBoxWithBody:(ChipmunkBody *)body bb:(cpBB)bb radius:(cpFloat)radius
316 {
317         if((self = [super init])){
318                 [body retain];
319                 cpBoxShapeInit2(&_shape, body.body, bb, radius);
320                 self.shape->userData = self;
321         }
322         
323         return self;
324 }
325
326 - (int)count {return cpPolyShapeGetCount((cpShape *)&_shape);}
327 - (cpFloat)radius {return cpPolyShapeGetRadius((cpShape *)&_shape);}
328 - (cpVect)getVertex:(int)index {return cpPolyShapeGetVert((cpShape *)&_shape, index);}
329
330 @end