chipmunk 5.3.4.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,504 @@
1
+ /* Copyright (c) 2007 Scott Lembcke
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
+ #include <stdlib.h>
23
+ #include "chipmunk.h"
24
+
25
+ #include "ruby.h"
26
+ #include "rb_chipmunk.h"
27
+
28
+ VALUE c_cpBody;
29
+ VALUE c_cpStaticBody;
30
+
31
+ static VALUE
32
+ rb_cpBodyAlloc(VALUE klass)
33
+ {
34
+ cpBody *body = cpBodyNew(1.0f, 1.0f);
35
+ return Data_Wrap_Struct(klass, NULL, cpBodyFree, body);
36
+ }
37
+
38
+ static VALUE
39
+ rb_cpBodyInitialize(VALUE self, VALUE m, VALUE i)
40
+ {
41
+ cpBody *body = BODY(self);
42
+ cpBodyInit(body, NUM2DBL(m), NUM2DBL(i));
43
+ body->data = (void *)self;
44
+ return self;
45
+ }
46
+
47
+ static VALUE
48
+ rb_cpBodyAllocStatic(VALUE klass)
49
+ {
50
+ cpBody *body = cpBodyNewStatic();
51
+ return Data_Wrap_Struct(c_cpStaticBody, NULL, cpBodyFree, body);
52
+ }
53
+
54
+ static VALUE
55
+ rb_cpBodyInitializeStatic(VALUE self)
56
+ {
57
+ cpBody *body = STATICBODY(self);
58
+ cpBodyInitStatic(body);
59
+ body->data = (void *)self;
60
+ return self;
61
+ }
62
+
63
+ static VALUE
64
+ rb_cpStaticBodyNew(VALUE klass) {
65
+ return rb_cpBodyInitializeStatic(rb_cpBodyAllocStatic(klass));
66
+ }
67
+
68
+
69
+ static VALUE
70
+ rb_cpBodyGetMass(VALUE self)
71
+ {
72
+ return rb_float_new(BODY(self)->m);
73
+ }
74
+
75
+ static VALUE
76
+ rb_cpBodyGetMassInv(VALUE self)
77
+ {
78
+ return rb_float_new(BODY(self)->m_inv);
79
+ }
80
+
81
+ static VALUE
82
+ rb_cpBodyGetMoment(VALUE self)
83
+ {
84
+ return rb_float_new(BODY(self)->i);
85
+ }
86
+
87
+
88
+ static VALUE
89
+ rb_cpBodyGetMomentInv(VALUE self)
90
+ {
91
+ return rb_float_new(BODY(self)->i_inv);
92
+ }
93
+
94
+ static VALUE
95
+ rb_cpBodyGetPos(VALUE self)
96
+ {
97
+ return VWRAP(self, &BODY(self)->p);
98
+ }
99
+
100
+ static VALUE
101
+ rb_cpBodyGetVel(VALUE self)
102
+ {
103
+ return VWRAP(self, &BODY(self)->v);
104
+ }
105
+
106
+ static VALUE
107
+ rb_cpBodyGetForce(VALUE self)
108
+ {
109
+ return VWRAP(self, &BODY(self)->f);
110
+ }
111
+
112
+ static VALUE
113
+ rb_cpBodyGetAngle(VALUE self)
114
+ {
115
+ return rb_float_new(BODY(self)->a);
116
+ }
117
+
118
+ static VALUE
119
+ rb_cpBodyGetAVel(VALUE self)
120
+ {
121
+ return rb_float_new(BODY(self)->w);
122
+ }
123
+
124
+ static VALUE
125
+ rb_cpBodyGetTorque(VALUE self)
126
+ {
127
+ return rb_float_new(BODY(self)->t);
128
+ }
129
+
130
+ static VALUE
131
+ rb_cpBodyGetVLimit(VALUE self)
132
+ {
133
+ return rb_float_new(BODY(self)->v_limit);
134
+ }
135
+
136
+ static VALUE
137
+ rb_cpBodyGetWLimit(VALUE self)
138
+ {
139
+ return rb_float_new(BODY(self)->w_limit);
140
+ }
141
+
142
+
143
+ static VALUE
144
+ rb_cpBodyGetRot(VALUE self)
145
+ {
146
+ return VWRAP(self, &BODY(self)->rot);
147
+ }
148
+
149
+
150
+ static VALUE
151
+ rb_cpBodySetMass(VALUE self, VALUE val)
152
+ {
153
+ cpBodySetMass(BODY(self), NUM2DBL(val));
154
+ return val;
155
+ }
156
+
157
+ static VALUE
158
+ rb_cpBodySetMoment(VALUE self, VALUE val)
159
+ {
160
+ cpBodySetMoment(BODY(self), NUM2DBL(val));
161
+ return val;
162
+ }
163
+
164
+ static VALUE
165
+ rb_cpBodySetPos(VALUE self, VALUE val)
166
+ {
167
+ BODY(self)->p = *VGET(val);
168
+ return val;
169
+ }
170
+
171
+ static VALUE
172
+ rb_cpBodySetVel(VALUE self, VALUE val)
173
+ {
174
+ BODY(self)->v = *VGET(val);
175
+ return val;
176
+ }
177
+
178
+ static VALUE
179
+ rb_cpBodySetForce(VALUE self, VALUE val)
180
+ {
181
+ BODY(self)->f = *VGET(val);
182
+ return val;
183
+ }
184
+
185
+ static VALUE
186
+ rb_cpBodySetAngle(VALUE self, VALUE val)
187
+ {
188
+ cpBodySetAngle(BODY(self), NUM2DBL(val));
189
+ return val;
190
+ }
191
+
192
+ static VALUE
193
+ rb_cpBodySetAVel(VALUE self, VALUE val)
194
+ {
195
+ BODY(self)->w = NUM2DBL(val);
196
+ return val;
197
+ }
198
+
199
+ static VALUE
200
+ rb_cpBodySetTorque(VALUE self, VALUE val)
201
+ {
202
+ BODY(self)->t = NUM2DBL(val);
203
+ return val;
204
+ }
205
+
206
+
207
+ static VALUE
208
+ rb_cpBodySetVLimit(VALUE self, VALUE val)
209
+ {
210
+ BODY(self)->v_limit = NUM2DBL(val);
211
+ return val;
212
+ }
213
+
214
+ static VALUE
215
+ rb_cpBodySetWLimit(VALUE self, VALUE val)
216
+ {
217
+ BODY(self)->w_limit = NUM2DBL(val);
218
+ return val;
219
+ }
220
+
221
+
222
+
223
+ static VALUE
224
+ rb_cpBodyLocal2World(VALUE self, VALUE v)
225
+ {
226
+ return VNEW(cpBodyLocal2World(BODY(self), *VGET(v)));
227
+ }
228
+
229
+ static VALUE
230
+ rb_cpBodyWorld2Local(VALUE self, VALUE v)
231
+ {
232
+ return VNEW(cpBodyWorld2Local(BODY(self), *VGET(v)));
233
+ }
234
+
235
+ static VALUE
236
+ rb_cpBodyResetForces(VALUE self)
237
+ {
238
+ cpBodyResetForces(BODY(self));
239
+ return self;
240
+ }
241
+
242
+ static VALUE
243
+ rb_cpBodyApplyForce(VALUE self, VALUE f, VALUE r)
244
+ {
245
+ cpBodyApplyForce(BODY(self), *VGET(f), *VGET(r));
246
+ return self;
247
+ }
248
+
249
+ static VALUE
250
+ rb_cpBodyApplyImpulse(VALUE self, VALUE j, VALUE r)
251
+ {
252
+ cpBodyApplyImpulse(BODY(self), *VGET(j), *VGET(r));
253
+ return self;
254
+ }
255
+
256
+ static VALUE
257
+ rb_cpBodyUpdateVelocity(VALUE self, VALUE g, VALUE dmp, VALUE dt)
258
+ {
259
+ cpBodyUpdateVelocity(BODY(self), *VGET(g), NUM2DBL(dmp), NUM2DBL(dt));
260
+ return self;
261
+ }
262
+
263
+ static VALUE
264
+ rb_cpBodyUpdatePosition(VALUE self, VALUE dt)
265
+ {
266
+ cpBodyUpdatePosition(BODY(self), NUM2DBL(dt));
267
+ return self;
268
+ }
269
+
270
+ static VALUE rb_cpBodyActivate(VALUE self) {
271
+ cpBodyActivate(BODY(self));
272
+ return self;
273
+ }
274
+
275
+ static cpBody * rb_cpBodySleepValidate(VALUE vbody) {
276
+ cpBody * body = BODY(vbody);
277
+ cpSpace *space = body->space;
278
+ if(!space) {
279
+ rb_raise(rb_eArgError, "Cannot put a body to sleep that has not been added to a space.");
280
+ return NULL;
281
+ }
282
+ if (cpBodyIsStatic(body) && cpBodyIsRogue(body)) {
283
+ rb_raise(rb_eArgError, "Rogue AND static bodies cannot be put to sleep.");
284
+ return NULL;
285
+ }
286
+ if(space->locked) {
287
+ rb_raise(rb_eArgError, "Bodies can not be put to sleep during a query or a call to Space#add_collision_func. Put these calls into a post-step callback using Space#add_collision_handler.");
288
+ return NULL;
289
+ }
290
+ return body;
291
+ }
292
+
293
+ static VALUE rb_cpBodySleep(VALUE self) {
294
+ cpBody * body = rb_cpBodySleepValidate(self);
295
+ cpBodySleep(body);
296
+ return self;
297
+ }
298
+
299
+ static VALUE rb_cpBodySleepWithGroup(VALUE self, VALUE vgroup) {
300
+ cpBody * group = NIL_P(vgroup) ? NULL : rb_cpBodySleepValidate(vgroup);
301
+ cpBody * body = rb_cpBodySleepValidate(self);
302
+
303
+ if (!cpBodyIsSleeping(group)) {
304
+ rb_raise(rb_eArgError, "Cannot use a non-sleeping body as a group identifier.");
305
+ }
306
+ cpBodySleepWithGroup(body, group);
307
+ return self;
308
+ }
309
+
310
+
311
+ static VALUE rb_cpBodyIsSleeping(VALUE self) {
312
+ return cpBodyIsSleeping(BODY(self)) ? Qtrue : Qfalse;
313
+ }
314
+
315
+ static VALUE rb_cpBodyIsStatic(VALUE self) {
316
+ cpBody * body = BODY(self);
317
+ cpBool stat = 0;
318
+ // cpBodyInitStatic(body);
319
+ stat = cpBodyIsStatic(body);
320
+ return stat ? Qtrue : Qfalse;
321
+ //
322
+ }
323
+
324
+ static VALUE rb_cpBodyIsRogue(VALUE self) {
325
+ return cpBodyIsRogue(BODY(self)) ? Qtrue : Qfalse;
326
+ }
327
+
328
+ ID id_velocity_func;
329
+ ID id_speed_func;
330
+
331
+ static int
332
+ respondsTo(VALUE obj, ID method) {
333
+ VALUE value = rb_funcall(obj, rb_intern("respond_to?"), 1, ID2SYM(method));
334
+ return RTEST(value);
335
+ }
336
+
337
+ /*
338
+
339
+ typedef void (*cpBodyVelocityFunc)(struct cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
340
+ typedef void (*cpBodyPositionFunc)(struct cpBody *body, cpFloat dt);
341
+ */
342
+
343
+ static void
344
+ bodyVelocityCallback(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) {
345
+ VALUE vbody = (VALUE)(body->data);
346
+ VALUE block = rb_iv_get(vbody, "velocity_func");
347
+ VALUE vgravity = VNEW(gravity);
348
+ VALUE vdamping = rb_float_new(damping);
349
+ VALUE vdt = rb_float_new(dt);
350
+ rb_funcall(block, rb_intern("call"), 4, vbody, vgravity, vdamping, vdt);
351
+ }
352
+
353
+ static VALUE
354
+ rb_cpBodySetVelocityFunc(int argc, VALUE *argv, VALUE self)
355
+ {
356
+ VALUE block;
357
+ cpBody * body = BODY(self);
358
+ rb_scan_args(argc, argv, "&", &block);
359
+ // Restore defaults if no block
360
+ if (NIL_P(block)) {
361
+ body->velocity_func = cpBodyUpdateVelocity; //Default;
362
+ return Qnil;
363
+ }
364
+ // set block for use in callback
365
+ rb_iv_set(self, "velocity_func", block);
366
+ body->velocity_func = bodyVelocityCallback;
367
+ return self;
368
+ }
369
+
370
+ static void
371
+ bodyPositionCallback(cpBody *body, cpFloat dt) {
372
+ VALUE vbody = (VALUE)(body->data);
373
+ VALUE block = rb_iv_get(vbody, "position_func");
374
+ VALUE vdt = rb_float_new(dt);
375
+ rb_funcall(block, rb_intern("call"), 2, vbody, vdt);
376
+ }
377
+
378
+ static VALUE
379
+ rb_cpBodySetPositionFunc(int argc, VALUE *argv, VALUE self)
380
+ {
381
+ VALUE block;
382
+ cpBody * body = BODY(self);
383
+ rb_scan_args(argc, argv, "&", &block);
384
+ // Restore defaults if no block
385
+ if (NIL_P(block)) {
386
+ body->position_func = cpBodyUpdatePosition; //Default;
387
+ return Qnil;
388
+ }
389
+ // set block for use in callback
390
+ rb_iv_set(self, "position_func", block);
391
+ body->position_func = bodyPositionCallback;
392
+ return self;
393
+ }
394
+
395
+ static VALUE
396
+ rb_cpBodyGetData(VALUE self) {
397
+ return rb_iv_get(self, "data");
398
+ }
399
+
400
+ static VALUE
401
+ rb_cpBodySetData(VALUE self, VALUE val) {
402
+ rb_iv_set(self, "data", val);
403
+ return val;
404
+ }
405
+
406
+
407
+ static VALUE
408
+ rb_cpBodySlew(VALUE self, VALUE pos, VALUE dt) {
409
+ cpBodySlew(BODY(self), *VGET(pos), NUM2DBL(dt));
410
+ return self;
411
+ }
412
+
413
+
414
+ void
415
+ Init_cpBody(void)
416
+ {
417
+ c_cpBody = rb_define_class_under(m_Chipmunk, "Body", rb_cObject);
418
+ rb_define_alloc_func(c_cpBody, rb_cpBodyAlloc);
419
+ rb_define_method(c_cpBody, "initialize", rb_cpBodyInitialize, 2);
420
+
421
+ c_cpStaticBody = rb_define_class_under(m_Chipmunk, "StaticBody", c_cpBody);
422
+ // rb_define_alloc_func will not work here, since superclass defines this.
423
+ // so, we define new here in stead.
424
+ rb_define_singleton_method(c_cpStaticBody, "new", rb_cpStaticBodyNew, 0);
425
+ rb_define_method(c_cpStaticBody, "initialize", rb_cpBodyInitializeStatic, 0);
426
+ rb_define_singleton_method(c_cpBody, "new_static", rb_cpStaticBodyNew, 0);
427
+
428
+ rb_define_method(c_cpBody, "m" , rb_cpBodyGetMass, 0);
429
+ rb_define_method(c_cpBody, "i" , rb_cpBodyGetMoment, 0);
430
+
431
+ rb_define_method(c_cpBody, "p" , rb_cpBodyGetPos, 0);
432
+ rb_define_method(c_cpBody, "v" , rb_cpBodyGetVel, 0);
433
+ rb_define_method(c_cpBody, "f" , rb_cpBodyGetForce, 0);
434
+ rb_define_method(c_cpBody, "a" , rb_cpBodyGetAngle, 0);
435
+ rb_define_method(c_cpBody, "w" , rb_cpBodyGetAVel, 0);
436
+ rb_define_method(c_cpBody, "t" , rb_cpBodyGetTorque, 0);
437
+ rb_define_method(c_cpBody, "rot" , rb_cpBodyGetRot, 0);
438
+
439
+ rb_define_method(c_cpBody, "m=", rb_cpBodySetMass, 1);
440
+ rb_define_method(c_cpBody, "i=", rb_cpBodySetMoment, 1);
441
+ rb_define_method(c_cpBody, "p=", rb_cpBodySetPos, 1);
442
+ rb_define_method(c_cpBody, "v=", rb_cpBodySetVel, 1);
443
+ rb_define_method(c_cpBody, "f=", rb_cpBodySetForce, 1);
444
+ rb_define_method(c_cpBody, "a=", rb_cpBodySetAngle, 1);
445
+ rb_define_method(c_cpBody, "w=", rb_cpBodySetAVel, 1);
446
+ rb_define_method(c_cpBody, "t=", rb_cpBodySetTorque, 1);
447
+
448
+ rb_define_method(c_cpBody, "mass" , rb_cpBodyGetMass, 0);
449
+ rb_define_method(c_cpBody, "moment" , rb_cpBodyGetMoment, 0);
450
+ rb_define_method(c_cpBody, "pos" , rb_cpBodyGetPos, 0);
451
+ rb_define_method(c_cpBody, "vel" , rb_cpBodyGetVel, 0);
452
+ rb_define_method(c_cpBody, "force" , rb_cpBodyGetForce, 0);
453
+ rb_define_method(c_cpBody, "angle" , rb_cpBodyGetAngle, 0);
454
+ rb_define_method(c_cpBody, "ang_vel" , rb_cpBodyGetAVel, 0);
455
+ rb_define_method(c_cpBody, "torque" , rb_cpBodyGetTorque, 0);
456
+ rb_define_method(c_cpBody, "rot", rb_cpBodyGetRot, 0);
457
+
458
+ rb_define_method(c_cpBody, "m_inv" , rb_cpBodyGetMassInv, 0);
459
+ rb_define_method(c_cpBody, "mass_inv" , rb_cpBodyGetMassInv, 0);
460
+ rb_define_method(c_cpBody, "moment_inv" , rb_cpBodyGetMomentInv, 0);
461
+ rb_define_method(c_cpBody, "v_limit" , rb_cpBodyGetVLimit, 0);
462
+ rb_define_method(c_cpBody, "w_limit" , rb_cpBodyGetWLimit, 0);
463
+
464
+
465
+ rb_define_method(c_cpBody, "mass=" , rb_cpBodySetMass, 1);
466
+ rb_define_method(c_cpBody, "moment=" , rb_cpBodySetMoment, 1);
467
+ rb_define_method(c_cpBody, "pos=" , rb_cpBodySetPos, 1);
468
+ rb_define_method(c_cpBody, "vel=" , rb_cpBodySetVel, 1);
469
+ rb_define_method(c_cpBody, "force=" , rb_cpBodySetForce, 1);
470
+ rb_define_method(c_cpBody, "angle=" , rb_cpBodySetAngle, 1);
471
+ rb_define_method(c_cpBody, "ang_vel=" , rb_cpBodySetAVel, 1);
472
+ rb_define_method(c_cpBody, "torque=" , rb_cpBodySetTorque, 1);
473
+ rb_define_method(c_cpBody, "v_limit=" , rb_cpBodySetVLimit, 1);
474
+ rb_define_method(c_cpBody, "w_limit=" , rb_cpBodySetWLimit, 1);
475
+
476
+
477
+ rb_define_method(c_cpBody, "local2world", rb_cpBodyLocal2World, 1);
478
+ rb_define_method(c_cpBody, "world2local", rb_cpBodyWorld2Local, 1);
479
+
480
+ rb_define_method(c_cpBody, "reset_forces", rb_cpBodyResetForces, 0);
481
+ rb_define_method(c_cpBody, "apply_force", rb_cpBodyApplyForce, 2);
482
+ rb_define_method(c_cpBody, "apply_impulse", rb_cpBodyApplyImpulse, 2);
483
+
484
+ rb_define_method(c_cpBody, "update_velocity", rb_cpBodyUpdateVelocity, 3);
485
+ rb_define_method(c_cpBody, "update_position", rb_cpBodyUpdatePosition, 1);
486
+ rb_define_method(c_cpBody, "slew" , rb_cpBodySlew , 2);
487
+
488
+ rb_define_method(c_cpBody, "static?", rb_cpBodyIsStatic, 0);
489
+ rb_define_method(c_cpBody, "rogue?", rb_cpBodyIsRogue, 0);
490
+ rb_define_method(c_cpBody, "sleeping?", rb_cpBodyIsSleeping, 0);
491
+ rb_define_method(c_cpBody, "sleep?", rb_cpBodyIsSleeping, 0);
492
+ rb_define_method(c_cpBody, "sleep_with_self" , rb_cpBodySleep, 0);
493
+ rb_define_method(c_cpBody, "sleep_self" , rb_cpBodySleep, 0);
494
+ rb_define_method(c_cpBody, "sleep_alone" , rb_cpBodySleep, 0);
495
+ rb_define_method(c_cpBody, "sleep_with_group", rb_cpBodySleepWithGroup, 1);
496
+ rb_define_method(c_cpBody, "sleep_group" , rb_cpBodySleepWithGroup, 1);
497
+ rb_define_method(c_cpBody, "activate" , rb_cpBodyActivate , 0);
498
+ rb_define_method(c_cpBody, "velocity_func" , rb_cpBodySetVelocityFunc, -1);
499
+ rb_define_method(c_cpBody, "position_func" , rb_cpBodySetPositionFunc, -1);
500
+
501
+ rb_define_method(c_cpBody, "object=" , rb_cpBodySetData, 1);
502
+ rb_define_method(c_cpBody, "object" , rb_cpBodyGetData, 0);
503
+
504
+ }