[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / third-party / chipmunk2d / objectivec / src / ChipmunkConstraint.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 - (ChipmunkConstraint *)addConstraint:(ChipmunkConstraint *)obj;
27 - (ChipmunkConstraint *)removeConstraint:(ChipmunkConstraint *)obj;
28
29 @end
30
31 @implementation ChipmunkConstraint
32
33 @synthesize userData = _userData;
34
35 +(ChipmunkConstraint *)constraintFromCPConstraint:(cpConstraint *)constraint
36 {       
37         ChipmunkConstraint *obj = constraint->userData;
38         cpAssertHard([obj isKindOfClass:[ChipmunkConstraint class]], "'constraint->data' is not a pointer to a ChipmunkConstraint object.");
39         
40         return obj;
41 }
42
43 - (void) dealloc
44 {
45         cpConstraint *constraint = self.constraint;
46         [self.bodyA release];
47         [self.bodyB release];
48         cpConstraintDestroy(constraint);
49         
50         [super dealloc];
51 }
52
53 - (cpConstraint *)constraint
54 {
55         [self doesNotRecognizeSelector:_cmd];
56         return nil;
57 }
58
59 // accessor macros
60 #define getter(type, lower, upper) \
61 - (type)lower {return cpConstraintGet##upper(self.constraint);}
62 #define setter(type, lower, upper) \
63 - (void)set##upper:(type)value {cpConstraintSet##upper(self.constraint, value);};
64 #define both(type, lower, upper) \
65 getter(type, lower, upper) \
66 setter(type, lower, upper)
67
68 both(cpFloat, maxForce, MaxForce)
69 both(cpFloat, errorBias, ErrorBias)
70 both(cpFloat, maxBias, MaxBias)
71 both(BOOL, collideBodies, CollideBodies)
72
73 -(cpFloat)impulse {return cpConstraintGetImpulse(self.constraint);}
74
75 -(ChipmunkSpace *)space {
76         cpSpace *space = cpConstraintGetSpace(self.constraint);
77         return (ChipmunkSpace *)(space ? cpSpaceGetUserData(space) : nil);
78 }
79
80 - (ChipmunkBody *)bodyA
81 {
82         cpBody *body = cpConstraintGetBodyA(self.constraint);
83         return (body ? cpBodyGetUserData(body) : nil);
84 }
85
86 //- (void)setBodyA:(ChipmunkBody *)value {
87 //      if(self.bodyA != value){
88 //              [self.bodyA release];
89 //              self.constraint->a = [[value retain] body];
90 //      }
91 //}
92
93 - (ChipmunkBody *)bodyB
94 {
95         cpBody *body = cpConstraintGetBodyB(self.constraint);
96         return (body ? cpBodyGetUserData(body) : nil);
97 }
98
99 //- (void)setBodyB:(ChipmunkBody *)value {
100 //      if(self.bodyB != value){
101 //              [self.bodyB release];
102 //              self.constraint->b = [[value retain] body];
103 //      }
104 //}
105
106 - (NSArray *)chipmunkObjects {return [NSArray arrayWithObject:self];}
107 - (void)addToSpace:(ChipmunkSpace *)space {[space addConstraint:self];}
108 - (void)removeFromSpace:(ChipmunkSpace *)space {[space removeConstraint:self];}
109
110 -(void)preSolve:(ChipmunkSpace *)space {}
111 -(void)postSolve:(ChipmunkSpace *)space {}
112
113 // MARK: Callbacks
114 static void
115 PreSolve(cpConstraint *constraint, cpSpace *space)
116 {
117         [(ChipmunkConstraint *)constraint->userData preSolve:(ChipmunkSpace *)space->userData];
118 }
119
120 static void
121 PostSolve(cpConstraint *constraint, cpSpace *space)
122 {
123         [(ChipmunkConstraint *)constraint->userData postSolve:(ChipmunkSpace *)space->userData];
124 }
125
126 // Check if the method was overridden.
127 // No reason to add the extra method overhead if it's not needed.
128 -(BOOL)methodIsOverriden:(SEL)selector
129 {
130         return ([self methodForSelector:selector] != [[ChipmunkConstraint class] instanceMethodForSelector:selector]);
131 }
132
133 -(void)setupCallbacks
134 {
135         if([self methodIsOverriden:@selector(preSolve:)]){
136                 cpConstraintSetPreSolveFunc(self.constraint, PreSolve);
137         }
138         
139         if([self methodIsOverriden:@selector(postSolve:)]){
140                 cpConstraintSetPostSolveFunc(self.constraint, PostSolve);
141         }
142 }
143
144 @end
145
146 // accessor macros
147 #define getter2(type, struct, lower, upper) \
148 - (type)lower {return struct##Get##upper((cpConstraint *)&_constraint);}
149 #define setter2(type, struct, lower, upper) \
150 - (void)set##upper:(type)value {struct##Set##upper((cpConstraint *)&_constraint, value);};
151 #define both2(type, struct, lower, upper) \
152 getter2(type, struct, lower, upper) \
153 setter2(type, struct, lower, upper)
154
155
156 @implementation ChipmunkPinJoint {
157         cpPinJoint _constraint;
158 }
159
160 + (id)pinJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB
161 {
162         return [[[self alloc] initWithBodyA:a bodyB:b anchorA:anchorA anchorB:anchorB] autorelease];
163 }
164
165 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
166
167 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB
168 {
169         if((self = [super init])){
170                 [a retain];
171                 [b retain];
172                 cpPinJointInit(&_constraint, a.body, b.body, anchorA, anchorB);
173                 self.constraint->userData = self;
174                 
175                 [self setupCallbacks];
176         }
177         
178         return self;
179 }
180
181 both2(cpVect, cpPinJoint, anchorA, AnchorA)
182 both2(cpVect, cpPinJoint, anchorB, AnchorB)
183 both2(cpFloat, cpPinJoint, dist, Dist)
184
185 @end
186
187
188 @implementation ChipmunkSlideJoint {
189         cpSlideJoint _constraint;
190 }
191
192 + (id)slideJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB min:(cpFloat)min max:(cpFloat)max
193 {
194         return [[[self alloc] initWithBodyA:a bodyB:b anchorA:anchorA anchorB:anchorB min:min max:max] autorelease];
195 }
196
197 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
198
199 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB min:(cpFloat)min max:(cpFloat)max
200 {
201         if((self = [super init])){
202                 [a retain];
203                 [b retain];
204                 cpSlideJointInit(&_constraint, a.body, b.body, anchorA, anchorB, min, max);
205                 self.constraint->userData = self;
206                 
207                 [self setupCallbacks];
208         }
209         
210         return self;
211 }
212
213 both2(cpVect, cpSlideJoint, anchorA, AnchorA)
214 both2(cpVect, cpSlideJoint, anchorB, AnchorB)
215 both2(cpFloat, cpSlideJoint, min, Min)
216 both2(cpFloat, cpSlideJoint, max, Max)
217
218 @end
219
220
221 @implementation ChipmunkPivotJoint {
222         cpPivotJoint _constraint;
223 }
224
225 + (id)pivotJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB
226 {
227         return [[[self alloc] initWithBodyA:a bodyB:b anchorA:anchorA anchorB:anchorB] autorelease];
228 }
229
230 + (id)pivotJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b pivot:(cpVect)pivot
231 {
232         return [[[self alloc] initWithBodyA:a bodyB:b pivot:pivot] autorelease];
233 }
234
235 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
236
237 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB
238 {
239         if((self = [super init])){
240                 [a retain];
241                 [b retain];
242                 cpPivotJointInit(&_constraint, a.body, b.body, anchorA, anchorB);
243                 self.constraint->userData = self;
244                 
245                 [self setupCallbacks];
246         }
247         
248         return self;
249 }
250
251 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b pivot:(cpVect)pivot
252 {
253         return [self initWithBodyA:a bodyB:b anchorA:[a worldToLocal:pivot] anchorB:[b worldToLocal:pivot]];
254 }
255
256 both2(cpVect, cpPivotJoint, anchorA, AnchorA)
257 both2(cpVect, cpPivotJoint, anchorB, AnchorB)
258
259 @end
260
261
262 @implementation ChipmunkGrooveJoint {
263         cpGrooveJoint _constraint;
264 }
265
266 + (id)grooveJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b grooveA:(cpVect)grooveA grooveB:(cpVect)grooveB anchorB:(cpVect)anchorB
267 {
268         return [[[self alloc] initWithBodyA:a bodyB:b grooveA:grooveA grooveB:grooveB anchorB:anchorB] autorelease];
269 }
270
271 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
272
273 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b grooveA:(cpVect)grooveA grooveB:(cpVect)grooveB anchorB:(cpVect)anchorB
274 {
275         if((self = [super init])){
276                 [a retain];
277                 [b retain];
278                 cpGrooveJointInit(&_constraint, a.body, b.body, grooveA, grooveB, anchorB);
279                 self.constraint->userData = self;
280                 
281                 [self setupCallbacks];
282         }
283         
284         return self;
285 }
286
287 both2(cpVect, cpGrooveJoint, grooveA, GrooveA)
288 both2(cpVect, cpGrooveJoint, grooveB, GrooveB)
289 both2(cpVect, cpGrooveJoint, anchorB, AnchorB)
290
291 @end
292
293
294 @implementation ChipmunkDampedSpring {
295         cpDampedSpring _constraint;
296 }
297
298 + (id)dampedSpringWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB restLength:(cpFloat)restLength stiffness:(cpFloat)stiffness damping:(cpFloat)damping
299 {
300         return [[[self alloc] initWithBodyA:a bodyB:b anchorA:anchorA anchorB:anchorB restLength:restLength stiffness:stiffness damping:damping] autorelease];
301 }
302
303 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
304
305 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB restLength:(cpFloat)restLength stiffness:(cpFloat)stiffness damping:(cpFloat)damping
306 {
307         if((self = [super init])){
308                 [a retain];
309                 [b retain];
310                 cpDampedSpringInit(&_constraint, a.body, b.body, anchorA, anchorB, restLength, stiffness, damping);
311                 self.constraint->userData = self;
312                 
313                 [self setupCallbacks];
314         }
315         
316         return self;
317 }
318
319 both2(cpVect, cpDampedSpring, anchorA, AnchorA)
320 both2(cpVect, cpDampedSpring, anchorB, AnchorB)
321 both2(cpFloat, cpDampedSpring, restLength, RestLength)
322 both2(cpFloat, cpDampedSpring, stiffness, Stiffness)
323 both2(cpFloat, cpDampedSpring, damping, Damping)
324
325 @end
326
327
328 @implementation ChipmunkDampedRotarySpring {
329         cpDampedRotarySpring _constraint;
330 }
331
332 + (id)dampedRotarySpringWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b restAngle:(cpFloat)restAngle stiffness:(cpFloat)stiffness damping:(cpFloat)damping
333 {
334         return [[[self alloc] initWithBodyA:a bodyB:b restAngle:restAngle stiffness:stiffness damping:damping] autorelease];
335 }
336
337 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
338
339 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b restAngle:(cpFloat)restAngle stiffness:(cpFloat)stiffness damping:(cpFloat)damping
340 {
341         if((self = [super init])){
342                 [a retain];
343                 [b retain];
344                 cpDampedRotarySpringInit(&_constraint, a.body, b.body, restAngle, stiffness, damping);
345                 self.constraint->userData = self;
346                 
347                 [self setupCallbacks];
348         }
349         
350         return self;
351 }
352
353 both2(cpFloat, cpDampedRotarySpring, restAngle, RestAngle)
354 both2(cpFloat, cpDampedRotarySpring, stiffness, Stiffness)
355 both2(cpFloat, cpDampedRotarySpring, damping, Damping)
356
357 @end
358
359
360 @implementation ChipmunkRotaryLimitJoint {
361         cpRotaryLimitJoint _constraint;
362 }
363
364 + (id)rotaryLimitJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b min:(cpFloat)min max:(cpFloat)max
365 {
366         return [[[self alloc] initWithBodyA:a bodyB:b min:min max:max] autorelease];
367 }
368
369 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
370
371 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b min:(cpFloat)min max:(cpFloat)max
372 {
373         if((self = [super init])){
374                 [a retain];
375                 [b retain];
376                 cpRotaryLimitJointInit(&_constraint, a.body, b.body, min, max);
377                 self.constraint->userData = self;
378                 
379                 [self setupCallbacks];
380         }
381         
382         return self;
383 }
384
385 both2(cpFloat, cpRotaryLimitJoint, min, Min)
386 both2(cpFloat, cpRotaryLimitJoint, max, Max)
387
388 @end
389
390
391 @implementation ChipmunkSimpleMotor {
392         cpSimpleMotor _constraint;
393 }
394
395 + (id)simpleMotorWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b rate:(cpFloat)rate
396 {
397         return [[[self alloc] initWithBodyA:a bodyB:b rate:rate] autorelease];
398 }
399
400 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
401
402 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b rate:(cpFloat)rate
403 {
404         if((self = [super init])){
405                 [a retain];
406                 [b retain];
407                 cpSimpleMotorInit(&_constraint, a.body, b.body, rate);
408                 self.constraint->userData = self;
409                 
410                 [self setupCallbacks];
411         }
412         
413         return self;
414 }
415
416 both2(cpFloat, cpSimpleMotor, rate, Rate)
417
418 @end
419
420
421 @implementation ChipmunkGearJoint {
422         cpGearJoint _constraint;
423 }
424
425 + (id)gearJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratio:(cpFloat)ratio
426 {
427         return [[[self alloc] initWithBodyA:a bodyB:b phase:phase ratio:ratio] autorelease];
428 }
429
430 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
431
432 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratio:(cpFloat)ratio
433 {
434         if((self = [super init])){
435                 [a retain];
436                 [b retain];
437                 cpGearJointInit(&_constraint, a.body, b.body, phase, ratio);
438                 self.constraint->userData = self;
439                 
440                 [self setupCallbacks];
441         }
442         
443         return self;
444 }
445
446 both2(cpFloat, cpGearJoint, phase, Phase)
447 both2(cpFloat, cpGearJoint, ratio, Ratio)
448
449 @end
450
451
452 @implementation ChipmunkRatchetJoint {
453         cpRatchetJoint _constraint;
454 }
455
456 + (id)ratchetJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratchet:(cpFloat)ratchet
457 {
458         return [[[self alloc] initWithBodyA:a bodyB:b phase:phase ratchet:ratchet] autorelease];
459 }
460
461 - (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
462
463 - (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratchet:(cpFloat)ratchet
464 {
465         if((self = [super init])){
466                 [a retain];
467                 [b retain];
468                 cpRatchetJointInit(&_constraint, a.body, b.body, phase, ratchet);
469                 self.constraint->userData = self;
470                 
471                 [self setupCallbacks];
472         }
473         
474         return self;
475 }
476
477 both2(cpFloat, cpRatchetJoint, angle, Angle)
478 both2(cpFloat, cpRatchetJoint, phase, Phase)
479 both2(cpFloat, cpRatchetJoint, ratchet, Ratchet)
480
481 @end