[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / third-party / chipmunk2d / objectivec / src / ChipmunkBody.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 - (ChipmunkBody *)addBody:(ChipmunkBody *)obj;
27 - (ChipmunkBody *)removeBody:(ChipmunkBody *)obj;
28
29 @end
30
31 @implementation ChipmunkBody {
32         cpBody _body;
33         id _userData;
34 }
35
36 // MARK: Integration Helpers
37
38 -(void)updateVelocity:(cpFloat)dt gravity:(cpVect)gravity damping:(cpFloat)damping
39 {
40         cpBodyUpdateVelocity(&_body, gravity, damping, dt);
41 }
42
43 -(void)updatePosition:(cpFloat)dt
44 {
45         cpBodyUpdatePosition(&_body, dt);
46 }
47
48 static void
49 VelocityFunction
50 (cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
51 {
52         [(ChipmunkBody *)body->userData updateVelocity:dt gravity:gravity damping:damping];
53 }
54
55 static void
56 PositionFunction
57 (cpBody *body, cpFloat dt)
58 {
59         [(ChipmunkBody *)body->userData updatePosition:dt];
60 }
61
62 // Check if the method was overridden.
63 // No reason to add the extra method overhead if it's not needed.
64 -(BOOL)methodIsOverriden:(SEL)selector
65 {
66         return ([self methodForSelector:selector] != [[ChipmunkBody class] instanceMethodForSelector:selector]);
67 }
68
69 // MARK: Constructors
70
71 +(ChipmunkBody *)bodyFromCPBody:(cpBody *)body
72 {       
73         ChipmunkBody *obj = body->userData;
74         cpAssertHard([obj isKindOfClass:[ChipmunkBody class]], "'body->data' is not a pointer to a ChipmunkBody object.");
75         
76         return obj;
77 }
78
79 + (id)bodyWithMass:(cpFloat)mass andMoment:(cpFloat)moment
80 {
81         return [[[self alloc] initWithMass:mass andMoment:moment] autorelease];
82 }
83
84 + (id)staticBody
85 {
86         ChipmunkBody *body = [[self alloc] initWithMass:0.0f andMoment:0.0f];
87         body.type = CP_BODY_TYPE_STATIC;
88         
89         return [body autorelease];
90 }
91
92 + (id)kinematicBody
93 {
94         ChipmunkBody *body = [[self alloc] initWithMass:0.0f andMoment:0.0f];
95         body.type = CP_BODY_TYPE_KINEMATIC;
96         
97         return [body autorelease];
98 }
99
100 - (id)initWithMass:(cpFloat)mass andMoment:(cpFloat)moment
101 {
102         if((self = [super init])){
103                 cpBodyInit(&_body, mass, moment);
104                 _body.userData = self;
105                 
106                 // Setup integration callbacks if necessary.
107                 if([self methodIsOverriden:@selector(updateVelocity:gravity:damping:)]){
108                         _body.velocity_func = VelocityFunction;
109                 }
110                 
111                 if([self methodIsOverriden:@selector(updatePosition:)]){
112                         _body.position_func = PositionFunction;
113                 }
114         }
115         
116         return self;
117 }
118
119 - (void) dealloc
120 {
121         cpBodyDestroy(&_body);
122         [super dealloc];
123 }
124
125 - (cpTransform)transform {return _body.transform;}
126 - (cpBody *)body {return &_body;}
127
128
129 @synthesize userData = _userData;
130
131 // accessor macros
132 #define getter(type, lower, upper) \
133 - (type)lower {return cpBodyGet##upper(&_body);}
134 #define setter(type, lower, upper) \
135 - (void)set##upper:(type)value {cpBodySet##upper(&_body, value);};
136 #define both(type, lower, upper) \
137 getter(type, lower, upper) \
138 setter(type, lower, upper)
139
140
141 both(cpBodyType, type, Type)
142 both(cpFloat, mass, Mass)
143 both(cpFloat, moment, Moment)
144 both(cpVect, centerOfGravity, CenterOfGravity)
145 both(cpVect, position, Position)
146 both(cpVect, velocity, Velocity)
147 both(cpVect, force, Force)
148 both(cpFloat, angle, Angle)
149 both(cpFloat, angularVelocity, AngularVelocity)
150 both(cpFloat, torque, Torque)
151
152 -(ChipmunkSpace *)space {
153         cpSpace *space = cpBodyGetSpace(&_body);
154         return (ChipmunkSpace *)(space ? cpSpaceGetUserData(space) : nil);
155 }
156
157 - (cpFloat)kineticEnergy {return cpBodyKineticEnergy(&_body);}
158
159 - (cpVect)localToWorld:(cpVect)v {return cpBodyLocalToWorld(&_body, v);}
160 - (cpVect)worldToLocal:(cpVect)v {return cpBodyWorldToLocal(&_body, v);}
161
162 - (cpVect)velocityAtLocalPoint:(cpVect)p {return cpBodyGetVelocityAtLocalPoint(&_body, p);}
163 - (cpVect)velocityAtWorldPoint:(cpVect)p {return cpBodyGetVelocityAtWorldPoint(&_body, p);}
164
165 - (void)applyForce:(cpVect)force atLocalPoint:(cpVect)point {cpBodyApplyForceAtLocalPoint(&_body, force, point);}
166 - (void)applyForce:(cpVect)force atWorldPoint:(cpVect)point {cpBodyApplyForceAtWorldPoint(&_body, force, point);}
167 - (void)applyImpulse:(cpVect)impulse atLocalPoint:(cpVect)point {cpBodyApplyImpulseAtLocalPoint(&_body, impulse, point);}
168 - (void)applyImpulse:(cpVect)impulse atWorldPoint:(cpVect)point {cpBodyApplyImpulseAtWorldPoint(&_body, impulse, point);}
169
170 - (bool)isSleeping {return cpBodyIsSleeping(&_body);}
171
172 - (void)activate {cpBodyActivate(&_body);}
173 - (void)activateStatic:(ChipmunkShape *)filter {cpBodyActivateStatic(&_body, filter.shape);}
174 - (void)sleepWithGroup:(ChipmunkBody *)group {cpBodySleepWithGroup(&_body, group.body);}
175 - (void)sleep {cpBodySleep(&_body);}
176
177 - (NSArray *)chipmunkObjects {return [NSArray arrayWithObject:self];}
178 - (void)addToSpace:(ChipmunkSpace *)space {[space addBody:self];}
179 - (void)removeFromSpace:(ChipmunkSpace *)space {[space removeBody:self];}
180
181 static void PushShape(cpBody *ignored, cpShape *shape, NSMutableArray *arr){[arr addObject:shape->userData];}
182 - (NSArray *)shapes
183 {
184         NSMutableArray *arr = [NSMutableArray array];
185         cpBodyEachShape(&_body, (cpBodyShapeIteratorFunc)PushShape, arr);
186         
187         return arr;
188 }
189
190 static void PushConstraint(cpBody *ignored, cpConstraint *constraint, NSMutableArray *arr){[arr addObject:constraint->userData];}
191 - (NSArray *)constraints
192 {
193         NSMutableArray *arr = [NSMutableArray array];
194         cpBodyEachConstraint(&_body, (cpBodyConstraintIteratorFunc)PushConstraint, arr);
195         
196         return arr;
197 }
198
199 static void CallArbiterBlock(cpBody *body, cpArbiter *arbiter, ChipmunkBodyArbiterIteratorBlock block){block(arbiter);}
200 - (void)eachArbiter:(ChipmunkBodyArbiterIteratorBlock)block
201 {
202         cpBodyEachArbiter(&_body, (cpBodyArbiterIteratorFunc)CallArbiterBlock, block);
203 }
204
205 @end