chipmunk 5.2.2 → 5.3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. data/LICENSE +21 -19
  2. data/README +67 -60
  3. data/Rakefile +85 -50
  4. data/ext/chipmunk/extconf.rb +42 -35
  5. data/ext/chipmunk/rb_chipmunk.c +250 -125
  6. data/ext/chipmunk/rb_chipmunk.h +105 -96
  7. data/ext/chipmunk/rb_cpArbiter.c +253 -225
  8. data/ext/chipmunk/rb_cpBB.c +210 -174
  9. data/ext/chipmunk/rb_cpBody.c +504 -347
  10. data/ext/chipmunk/rb_cpConstraint.c +336 -346
  11. data/ext/chipmunk/rb_cpShape.c +433 -455
  12. data/ext/chipmunk/rb_cpSpace.c +711 -544
  13. data/ext/chipmunk/rb_cpVect.c +346 -321
  14. data/lib/chipmunk.rb +183 -30
  15. metadata +12 -66
  16. data/ext/chipmunk/chipmunk.c +0 -105
  17. data/ext/chipmunk/cpArbiter.c +0 -274
  18. data/ext/chipmunk/cpArray.c +0 -128
  19. data/ext/chipmunk/cpBB.c +0 -47
  20. data/ext/chipmunk/cpBody.c +0 -188
  21. data/ext/chipmunk/cpCollision.c +0 -391
  22. data/ext/chipmunk/cpConstraint.c +0 -54
  23. data/ext/chipmunk/cpDampedRotarySpring.c +0 -106
  24. data/ext/chipmunk/cpDampedSpring.c +0 -117
  25. data/ext/chipmunk/cpGearJoint.c +0 -114
  26. data/ext/chipmunk/cpGrooveJoint.c +0 -138
  27. data/ext/chipmunk/cpHashSet.c +0 -253
  28. data/ext/chipmunk/cpPinJoint.c +0 -117
  29. data/ext/chipmunk/cpPivotJoint.c +0 -114
  30. data/ext/chipmunk/cpPolyShape.c +0 -241
  31. data/ext/chipmunk/cpRatchetJoint.c +0 -128
  32. data/ext/chipmunk/cpRotaryLimitJoint.c +0 -122
  33. data/ext/chipmunk/cpShape.c +0 -400
  34. data/ext/chipmunk/cpSimpleMotor.c +0 -99
  35. data/ext/chipmunk/cpSlideJoint.c +0 -131
  36. data/ext/chipmunk/cpSpace.c +0 -899
  37. data/ext/chipmunk/cpSpaceHash.c +0 -541
  38. data/ext/chipmunk/cpVect.c +0 -71
  39. data/ext/chipmunk/include/chipmunk/chipmunk.h +0 -148
  40. data/ext/chipmunk/include/chipmunk/chipmunk_ffi.h +0 -42
  41. data/ext/chipmunk/include/chipmunk/chipmunk_types.h +0 -80
  42. data/ext/chipmunk/include/chipmunk/chipmunk_unsafe.h +0 -54
  43. data/ext/chipmunk/include/chipmunk/constraints/cpConstraint.h +0 -92
  44. data/ext/chipmunk/include/chipmunk/constraints/cpDampedRotarySpring.h +0 -46
  45. data/ext/chipmunk/include/chipmunk/constraints/cpDampedSpring.h +0 -53
  46. data/ext/chipmunk/include/chipmunk/constraints/cpGearJoint.h +0 -41
  47. data/ext/chipmunk/include/chipmunk/constraints/cpGrooveJoint.h +0 -44
  48. data/ext/chipmunk/include/chipmunk/constraints/cpPinJoint.h +0 -43
  49. data/ext/chipmunk/include/chipmunk/constraints/cpPivotJoint.h +0 -42
  50. data/ext/chipmunk/include/chipmunk/constraints/cpRatchetJoint.h +0 -40
  51. data/ext/chipmunk/include/chipmunk/constraints/cpRotaryLimitJoint.h +0 -39
  52. data/ext/chipmunk/include/chipmunk/constraints/cpSimpleMotor.h +0 -37
  53. data/ext/chipmunk/include/chipmunk/constraints/cpSlideJoint.h +0 -44
  54. data/ext/chipmunk/include/chipmunk/constraints/util.h +0 -116
  55. data/ext/chipmunk/include/chipmunk/cpArbiter.h +0 -136
  56. data/ext/chipmunk/include/chipmunk/cpArray.h +0 -46
  57. data/ext/chipmunk/include/chipmunk/cpBB.h +0 -74
  58. data/ext/chipmunk/include/chipmunk/cpBody.h +0 -160
  59. data/ext/chipmunk/include/chipmunk/cpCollision.h +0 -23
  60. data/ext/chipmunk/include/chipmunk/cpHashSet.h +0 -82
  61. data/ext/chipmunk/include/chipmunk/cpPolyShape.h +0 -103
  62. data/ext/chipmunk/include/chipmunk/cpShape.h +0 -174
  63. data/ext/chipmunk/include/chipmunk/cpSpace.h +0 -180
  64. data/ext/chipmunk/include/chipmunk/cpSpaceHash.h +0 -109
  65. data/ext/chipmunk/include/chipmunk/cpVect.h +0 -157
  66. data/ext/chipmunk/prime.h +0 -68
  67. data/lib/chipmunk/version.rb +0 -3
@@ -1,544 +1,711 @@
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
- static ID id_call;
29
- static ID id_begin;
30
- static ID id_pre_solve;
31
- static ID id_post_solve;
32
- static ID id_separate;
33
-
34
-
35
- VALUE c_cpSpace;
36
-
37
- static VALUE
38
- rb_cpSpaceAlloc(VALUE klass)
39
- {
40
- cpSpace *space = cpSpaceAlloc();
41
- return Data_Wrap_Struct(klass, NULL, cpSpaceFree, space);
42
- }
43
-
44
- static VALUE
45
- rb_cpSpaceInitialize(VALUE self)
46
- {
47
- cpSpace *space = SPACE(self);
48
- cpSpaceInit(space);
49
-
50
- // These might as well be in one shared hash.
51
- rb_iv_set(self, "static_shapes", rb_ary_new());
52
- rb_iv_set(self, "active_shapes", rb_ary_new());
53
- rb_iv_set(self, "bodies", rb_ary_new());
54
- rb_iv_set(self, "constraints", rb_ary_new());
55
- rb_iv_set(self, "blocks", rb_hash_new());
56
-
57
- return self;
58
- }
59
-
60
- static VALUE
61
- rb_cpSpaceGetIterations(VALUE self)
62
- {
63
- return INT2NUM(SPACE(self)->iterations);
64
- }
65
-
66
- static VALUE
67
- rb_cpSpaceSetIterations(VALUE self, VALUE val)
68
- {
69
- SPACE(self)->iterations = NUM2INT(val);
70
- return val;
71
- }
72
-
73
- static VALUE
74
- rb_cpSpaceGetElasticIterations(VALUE self)
75
- {
76
- return INT2NUM(SPACE(self)->elasticIterations);
77
- }
78
-
79
- static VALUE
80
- rb_cpSpaceSetElasticIterations(VALUE self, VALUE val)
81
- {
82
- SPACE(self)->elasticIterations = NUM2INT(val);
83
- return val;
84
- }
85
-
86
- static VALUE
87
- rb_cpSpaceGetDamping(VALUE self)
88
- {
89
- return rb_float_new(SPACE(self)->damping);
90
- }
91
-
92
- static VALUE
93
- rb_cpSpaceSetDamping(VALUE self, VALUE val)
94
- {
95
- SPACE(self)->damping = NUM2DBL(val);
96
- return val;
97
- }
98
-
99
- static VALUE
100
- rb_cpSpaceGetGravity(VALUE self)
101
- {
102
- return VWRAP(self, &SPACE(self)->gravity);
103
- }
104
-
105
- static VALUE
106
- rb_cpSpaceSetGravity(VALUE self, VALUE val)
107
- {
108
- SPACE(self)->gravity = *VGET(val);
109
- return val;
110
- }
111
-
112
- #define respondsTo(obj, id) rb_respond_to(obj, id)
113
-
114
- static int
115
- isBlock(VALUE obj)
116
- {
117
- return rb_respond_to(obj, id_call);
118
- }
119
-
120
- static VALUE
121
- callbackToMethod(VALUE obj, ID func) {
122
- return rb_funcall(obj, rb_intern("method"), 1, ID2SYM(func));
123
- }
124
-
125
- static VALUE
126
- callbackArity(VALUE callback) {
127
- return rb_funcall(callback, rb_intern("arity"), 0, 0);
128
- }
129
-
130
- static int
131
- doNothingCallback(cpArbiter *arb, cpSpace *space, void *data)
132
- {
133
- return 0;
134
- }
135
-
136
- /* This callback can also pass arbiters... */
137
- static int
138
- genericCallback(cpArbiter *arb, cpSpace * space,
139
- void * data, ID func)
140
- {
141
- int arity = 3;
142
- /* int arity = rb_obj_method_arity((VALUE) data, func); */
143
- /* XXX: this doesn't work. */
144
- VALUE arbiter = Qnil;
145
- cpShape *a = NULL;
146
- cpShape *b = NULL;
147
- VALUE proc = Qnil;
148
- VALUE block = (VALUE) data;
149
- VALUE result;
150
-
151
- if(isBlock(block)) {
152
- proc = block;
153
- } else {
154
- proc = callbackToMethod((VALUE) data, func);
155
- }
156
-
157
- arity = NUM2INT(callbackArity(proc));
158
-
159
- switch (arity) {
160
- case -1:
161
- result = rb_funcall(proc, id_call, 3, (VALUE)a->data, (VALUE)b->data, arbiter);
162
- break;
163
- case 0:
164
- result = rb_funcall(proc, id_call, 0);
165
- break;
166
- case 1:
167
- arbiter = ARBWRAP(arb);
168
- result = rb_funcall(proc, id_call, 1, arbiter);
169
- break;
170
- case 2:
171
- cpArbiterGetShapes(arb, &a, &b);
172
- result = rb_funcall(proc, id_call, 2, (VALUE)a->data, (VALUE)b->data);
173
- break;
174
- case 3:
175
- cpArbiterGetShapes(arb, &a, &b);
176
- arbiter = ARBWRAP(arb);
177
- result = rb_funcall(proc, id_call, 3, (VALUE)a->data, (VALUE)b->data, arbiter);
178
- break;
179
- default:
180
- rb_raise(rb_eArgError, "Arity of callback must be -1, 0, 1, 2, or 3.");
181
- break;
182
- }
183
- return (RTEST(result) ? 1 : 0);
184
-
185
- }
186
-
187
- static int
188
- compatibilityCallback(cpArbiter *arb, cpSpace *space, void *data)
189
- {
190
- /*CP_ARBITER_GET_SHAPES(arb, a, b);
191
- return rb_funcall((VALUE)data, id_call, 2, (VALUE)a->data, (VALUE)b->data);
192
- */
193
- return genericCallback(arb, space, data, id_call);
194
- }
195
-
196
- static int
197
- beginCallback(cpArbiter *arb, cpSpace *space, void *data)
198
- {
199
- return genericCallback(arb, space, data, id_begin);
200
- }
201
-
202
- static int
203
- preSolveCallback(cpArbiter *arb, cpSpace *space, void *data)
204
- {
205
- return genericCallback(arb, space, data, id_pre_solve);
206
- }
207
-
208
- static void
209
- postSolveCallback(cpArbiter *arb, cpSpace *space, void *data)
210
- {
211
- genericCallback(arb, space, data, id_post_solve);}
212
-
213
- static void
214
- separateCallback(cpArbiter *arb, cpSpace *space, void *data)
215
- {
216
- genericCallback(arb, space, data, id_separate);
217
- }
218
-
219
-
220
- static VALUE
221
- rb_cpSpaceAddCollisionHandler(int argc, VALUE *argv, VALUE self)
222
- {
223
- VALUE a, b, obj, block;
224
- obj = 0;
225
- rb_scan_args(argc, argv, "21&", &a, &b, &obj, &block);
226
-
227
- VALUE id_a = rb_obj_id(a);
228
- VALUE id_b = rb_obj_id(b);
229
- VALUE blocks = rb_iv_get(self, "blocks");
230
-
231
- if(RTEST(obj) && RTEST(block)){
232
- rb_raise(rb_eArgError, "Cannot specify both a handler object and a block.");
233
- } else if(RTEST(block)){
234
- cpSpaceAddCollisionHandler(
235
- SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b),
236
- NULL,
237
- compatibilityCallback,
238
- NULL,
239
- NULL,
240
- (void *)block
241
- );
242
-
243
- rb_hash_aset(blocks, rb_ary_new3(2, id_a, id_b), block);
244
- } else if(RTEST(obj)) {
245
- // Do we need to make it pass arbiters??? FFI bindings also don't bother.
246
- cpSpaceAddCollisionHandler(
247
- SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b),
248
- (respondsTo(obj, id_begin) ? beginCallback : NULL),
249
- (respondsTo(obj, id_pre_solve) ? preSolveCallback : NULL),
250
- (respondsTo(obj, id_post_solve) ? postSolveCallback : NULL),
251
- (respondsTo(obj, id_separate) ? separateCallback : NULL),
252
- (void *)obj
253
- );
254
- rb_hash_aset(blocks, rb_ary_new3(2, id_a, id_b), obj);
255
- } else {
256
- cpSpaceAddCollisionHandler(
257
- SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b),
258
- NULL, doNothingCallback, NULL, NULL, NULL
259
- );
260
- }
261
-
262
- return Qnil;
263
- }
264
-
265
- static VALUE
266
- rb_cpSpaceRemoveCollisionHandler(VALUE self, VALUE a, VALUE b)
267
- {
268
- VALUE id_a = rb_obj_id(a);
269
- VALUE id_b = rb_obj_id(b);
270
- cpSpaceRemoveCollisionHandler(SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b));
271
-
272
- VALUE blocks = rb_iv_get(self, "blocks");
273
- rb_hash_delete(blocks, rb_ary_new3(2, id_a, id_b));
274
-
275
- return Qnil;
276
- }
277
-
278
- static VALUE
279
- rb_cpSpaceSetDefaultCollisionHandler(int argc, VALUE *argv, VALUE self)
280
- {
281
- VALUE obj, block;
282
- rb_scan_args(argc, argv, "01&", &obj, &block);
283
-
284
- if(RTEST(obj) && RTEST(block)){
285
- rb_raise(rb_eArgError, "Cannot specify both a handler object and a block.");
286
- } else if(RTEST(block)){
287
- // Do we need need to make it pass arbiters? FFI bindings don't do it.
288
- cpSpaceSetDefaultCollisionHandler(
289
- SPACE(self),
290
- NULL,
291
- compatibilityCallback,
292
- NULL,
293
- NULL,
294
- (void *)block
295
- );
296
-
297
- rb_hash_aset(rb_iv_get(self, "blocks"), ID2SYM(rb_intern("default")), block);
298
- } else if(RTEST(obj)) {
299
- cpSpaceSetDefaultCollisionHandler(
300
- SPACE(self),
301
- (respondsTo(obj, id_begin) ? beginCallback : NULL),
302
- (respondsTo(obj, id_pre_solve) ? preSolveCallback : NULL),
303
- (respondsTo(obj, id_post_solve) ? postSolveCallback : NULL),
304
- (respondsTo(obj, id_separate) ? separateCallback : NULL),
305
- (void *)obj
306
- );
307
-
308
- rb_hash_aset(rb_iv_get(self, "blocks"), ID2SYM(rb_intern("default")), obj);
309
- } else {
310
- cpSpaceSetDefaultCollisionHandler(
311
- SPACE(self), NULL, doNothingCallback, NULL, NULL, NULL
312
- );
313
- }
314
-
315
- return Qnil;
316
- }
317
-
318
- static VALUE
319
- rb_cpSpaceAddShape(VALUE self, VALUE shape)
320
- {
321
- cpSpaceAddShape(SPACE(self), SHAPE(shape));
322
- rb_ary_push(rb_iv_get(self, "active_shapes"), shape);
323
- return shape;
324
- }
325
-
326
- static VALUE
327
- rb_cpSpaceAddStaticShape(VALUE self, VALUE shape)
328
- {
329
- cpSpaceAddStaticShape(SPACE(self), SHAPE(shape));
330
- rb_ary_push(rb_iv_get(self, "static_shapes"), shape);
331
- return shape;
332
- }
333
-
334
- static VALUE
335
- rb_cpSpaceAddBody(VALUE self, VALUE body)
336
- {
337
- cpSpaceAddBody(SPACE(self), BODY(body));
338
- rb_ary_push(rb_iv_get(self, "bodies"), body);
339
- return body;
340
- }
341
-
342
- static VALUE
343
- rb_cpSpaceAddConstraint(VALUE self, VALUE constraint)
344
- {
345
- cpSpaceAddConstraint(SPACE(self), CONSTRAINT(constraint));
346
- rb_ary_push(rb_iv_get(self, "constraints"), constraint);
347
- return constraint;
348
- }
349
-
350
- static VALUE
351
- rb_cpSpaceRemoveShape(VALUE self, VALUE shape)
352
- {
353
- cpSpaceRemoveShape(SPACE(self), SHAPE(shape));
354
- return rb_ary_delete(rb_iv_get(self, "active_shapes"), shape);
355
- }
356
-
357
- static VALUE
358
- rb_cpSpaceRemoveStaticShape(VALUE self, VALUE shape)
359
- {
360
- cpSpaceRemoveStaticShape(SPACE(self), SHAPE(shape));
361
- return rb_ary_delete(rb_iv_get(self, "static_shapes"), shape);
362
- }
363
-
364
- static VALUE
365
- rb_cpSpaceRemoveBody(VALUE self, VALUE body)
366
- {
367
- cpSpaceRemoveBody(SPACE(self), BODY(body));
368
- return rb_ary_delete(rb_iv_get(self, "bodies"), body);
369
- }
370
-
371
- static VALUE
372
- rb_cpSpaceRemoveConstraint(VALUE self, VALUE constraint)
373
- {
374
- cpSpaceRemoveConstraint(SPACE(self), CONSTRAINT(constraint));
375
- return rb_ary_delete(rb_iv_get(self, "constraints"), constraint);
376
- }
377
-
378
- static VALUE
379
- rb_cpSpaceResizeStaticHash(VALUE self, VALUE dim, VALUE count)
380
- {
381
- cpSpaceResizeStaticHash(SPACE(self), NUM2DBL(dim), NUM2INT(count));
382
- return Qnil;
383
- }
384
-
385
- static VALUE
386
- rb_cpSpaceResizeActiveHash(VALUE self, VALUE dim, VALUE count)
387
- {
388
- cpSpaceResizeActiveHash(SPACE(self), NUM2DBL(dim), NUM2INT(count));
389
- return Qnil;
390
- }
391
-
392
- static VALUE
393
- rb_cpSpaceRehashStatic(VALUE self)
394
- {
395
- cpSpaceRehashStatic(SPACE(self));
396
- return Qnil;
397
- }
398
-
399
- static void
400
- pointQueryCallback(cpShape *shape, VALUE block)
401
- {
402
- rb_funcall(block, id_call, 1, (VALUE)shape->data);
403
- }
404
-
405
- static VALUE
406
- rb_cpSpacePointQuery(int argc, VALUE *argv, VALUE self)
407
- {
408
- VALUE point, layers, group, block;
409
- rb_scan_args(argc, argv, "12&", &point, &layers, &group, &block);
410
-
411
- cpSpacePointQuery(
412
- SPACE(self), *VGET(point),
413
- (NIL_P(layers) ? ~0 : NUM2UINT(layers)),
414
- (NIL_P(group) ? 0 : NUM2UINT(rb_obj_id(group))),
415
- (cpSpacePointQueryFunc)pointQueryCallback, (void *)block
416
- );
417
-
418
- return Qnil;
419
- }
420
-
421
- static VALUE
422
- rb_cpSpacePointQueryFirst(int argc, VALUE *argv, VALUE self)
423
- {
424
- VALUE point, layers, group;
425
- rb_scan_args(argc, argv, "12", &point, &layers, &group);
426
-
427
- cpShape *shape = cpSpacePointQueryFirst(
428
- SPACE(self), *VGET(point),
429
- (NIL_P(layers) ? ~0 : NUM2UINT(layers)),
430
- (NIL_P(group) ? 0 : NUM2UINT(rb_obj_id(group)))
431
- );
432
-
433
- return (shape ? (VALUE)shape->data : Qnil);
434
- }
435
-
436
- static void
437
- segmentQueryCallback(cpShape *shape, cpFloat t, cpVect n, VALUE block)
438
- {
439
- rb_funcall(block, id_call, 1, (VALUE)shape->data, rb_float_new(t), VNEW(n));
440
- }
441
-
442
- static VALUE
443
- rb_cpSpaceSegmentQuery(int argc, VALUE *argv, VALUE self)
444
- {
445
- VALUE a, b, layers, group, block;
446
- rb_scan_args(argc, argv, "22&", &a, &b, &layers, &group, &block);
447
-
448
- cpSpaceSegmentQuery(
449
- SPACE(self), *VGET(a), *VGET(b),
450
- (NIL_P(layers) ? ~0 : NUM2UINT(layers)),
451
- (NIL_P(group) ? 0 : NUM2UINT(rb_obj_id(group))),
452
- (cpSpaceSegmentQueryFunc)segmentQueryCallback, (void *)block
453
- );
454
-
455
- return Qnil;
456
- }
457
-
458
- static VALUE
459
- rb_cpSpaceSegmentQueryFirst(int argc, VALUE *argv, VALUE self)
460
- {
461
- VALUE a, b, layers, group, block;
462
- rb_scan_args(argc, argv, "22&", &a, &b, &layers, &group, &block);
463
-
464
- cpSegmentQueryInfo info = {NULL, 1.0f, cpvzero};
465
-
466
- cpSpaceSegmentQueryFirst(
467
- SPACE(self), *VGET(a), *VGET(b),
468
- (NIL_P(layers) ? ~0 : NUM2UINT(layers)),
469
- (NIL_P(group) ? 0 : NUM2UINT(rb_obj_id(group))),
470
- &info
471
- );
472
-
473
- if(info.shape){
474
- return rb_ary_new3(3, (VALUE)info.shape->data, rb_float_new(info.t), VNEW(info.n));
475
- } else {
476
- return Qnil;
477
- }
478
- }
479
-
480
- static VALUE
481
- rb_cpSpaceStep(VALUE self, VALUE dt)
482
- {
483
- cpSpaceStep(SPACE(self), NUM2DBL(dt));
484
- return Qnil;
485
- }
486
-
487
-
488
-
489
- void
490
- Init_cpSpace(void)
491
- {
492
- id_call = rb_intern("call");
493
- id_begin = rb_intern("begin");
494
- id_pre_solve = rb_intern("pre_solve");
495
- id_post_solve = rb_intern("post_solve");
496
- id_separate = rb_intern("separate");
497
-
498
- c_cpSpace = rb_define_class_under(m_Chipmunk, "Space", rb_cObject);
499
- rb_define_alloc_func(c_cpSpace, rb_cpSpaceAlloc);
500
- rb_define_method(c_cpSpace, "initialize", rb_cpSpaceInitialize, 0);
501
-
502
- rb_define_method(c_cpSpace, "iterations", rb_cpSpaceGetIterations, 0);
503
- rb_define_method(c_cpSpace, "iterations=", rb_cpSpaceSetIterations, 1);
504
-
505
- rb_define_method(c_cpSpace, "elastic_iterations", rb_cpSpaceGetElasticIterations, 0);
506
- rb_define_method(c_cpSpace, "elastic_iterations=", rb_cpSpaceSetElasticIterations, 1);
507
-
508
- rb_define_method(c_cpSpace, "damping", rb_cpSpaceGetDamping, 0);
509
- rb_define_method(c_cpSpace, "damping=", rb_cpSpaceSetDamping, 1);
510
-
511
- rb_define_method(c_cpSpace, "gravity", rb_cpSpaceGetGravity, 0);
512
- rb_define_method(c_cpSpace, "gravity=", rb_cpSpaceSetGravity, 1);
513
-
514
- rb_define_method(c_cpSpace, "add_collision_func", rb_cpSpaceAddCollisionHandler, -1);
515
- rb_define_method(c_cpSpace, "remove_collision_func", rb_cpSpaceRemoveCollisionHandler, 2);
516
- rb_define_method(c_cpSpace, "set_default_collision_func", rb_cpSpaceSetDefaultCollisionHandler, -1);
517
-
518
- rb_define_method(c_cpSpace, "add_collision_handler", rb_cpSpaceAddCollisionHandler, -1);
519
- rb_define_method(c_cpSpace, "remove_collision_handler", rb_cpSpaceRemoveCollisionHandler, 2);
520
- rb_define_method(c_cpSpace, "set_default_collision_handler", rb_cpSpaceSetDefaultCollisionHandler, -1);
521
-
522
-
523
- rb_define_method(c_cpSpace, "add_shape", rb_cpSpaceAddShape, 1);
524
- rb_define_method(c_cpSpace, "add_static_shape", rb_cpSpaceAddStaticShape, 1);
525
- rb_define_method(c_cpSpace, "add_body", rb_cpSpaceAddBody, 1);
526
- rb_define_method(c_cpSpace, "add_constraint", rb_cpSpaceAddConstraint, 1);
527
-
528
- rb_define_method(c_cpSpace, "remove_shape", rb_cpSpaceRemoveShape, 1);
529
- rb_define_method(c_cpSpace, "remove_static_shape", rb_cpSpaceRemoveStaticShape, 1);
530
- rb_define_method(c_cpSpace, "remove_body", rb_cpSpaceRemoveBody, 1);
531
- rb_define_method(c_cpSpace, "remove_constraint", rb_cpSpaceRemoveConstraint, 1);
532
-
533
- rb_define_method(c_cpSpace, "resize_static_hash", rb_cpSpaceResizeStaticHash, 2);
534
- rb_define_method(c_cpSpace, "resize_active_hash", rb_cpSpaceResizeActiveHash, 2);
535
- rb_define_method(c_cpSpace, "rehash_static", rb_cpSpaceRehashStatic, 0);
536
-
537
- rb_define_method(c_cpSpace, "point_query", rb_cpSpacePointQuery, -1);
538
- rb_define_method(c_cpSpace, "point_query_first", rb_cpSpacePointQueryFirst, -1);
539
-
540
- rb_define_method(c_cpSpace, "segment_query", rb_cpSpaceSegmentQuery, -1);
541
- rb_define_method(c_cpSpace, "segment_query_first", rb_cpSpaceSegmentQueryFirst, -1);
542
-
543
- rb_define_method(c_cpSpace, "step", rb_cpSpaceStep, 1);
544
- }
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
+ static ID id_call;
29
+ static ID id_begin;
30
+ static ID id_pre_solve;
31
+ static ID id_post_solve;
32
+ static ID id_separate;
33
+
34
+
35
+ VALUE c_cpSpace;
36
+
37
+
38
+ static VALUE
39
+ rb_cpSpaceAlloc(VALUE klass)
40
+ {
41
+ cpSpace *space = cpSpaceAlloc();
42
+ return Data_Wrap_Struct(klass, NULL, cpSpaceFree, space);
43
+ }
44
+
45
+ static VALUE
46
+ rb_cpSpaceInitialize(VALUE self)
47
+ {
48
+ cpSpace *space = SPACE(self);
49
+ cpSpaceInit(space);
50
+
51
+ // These might as well be in one shared hash.
52
+ rb_iv_set(self, "static_shapes", rb_ary_new());
53
+ rb_iv_set(self, "active_shapes", rb_ary_new());
54
+ rb_iv_set(self, "bodies", rb_ary_new());
55
+ rb_iv_set(self, "constraints", rb_ary_new());
56
+ rb_iv_set(self, "blocks", rb_hash_new());
57
+
58
+ return self;
59
+ }
60
+
61
+ static VALUE
62
+ SPACEWRAP(cpSpace * space) {
63
+ return Data_Wrap_Struct(c_cpSpace, NULL, cpSpaceFree, space);
64
+ }
65
+
66
+ static VALUE
67
+ rb_cpSpaceGetSleepTimeThreshold(VALUE self) {
68
+ return INT2NUM(SPACE(self)->sleepTimeThreshold);
69
+ }
70
+
71
+ static VALUE
72
+ rb_cpSpaceSetSleepTimeThreshold(VALUE self, VALUE val) {
73
+ SPACE(self)->sleepTimeThreshold = NUM2INT(val);
74
+ return val;
75
+ }
76
+
77
+ static VALUE
78
+ rb_cpSpaceGetIdleSpeedThreshold(VALUE self) {
79
+ return INT2NUM(SPACE(self)->idleSpeedThreshold);
80
+ }
81
+
82
+ static VALUE
83
+ rb_cpSpaceSetIdleSpeedThreshold(VALUE self, VALUE val) {
84
+ SPACE(self)->idleSpeedThreshold = NUM2INT(val);
85
+ return val;
86
+ }
87
+
88
+
89
+
90
+ static VALUE
91
+ rb_cpSpaceGetIterations(VALUE self)
92
+ {
93
+ return INT2NUM(SPACE(self)->iterations);
94
+ }
95
+
96
+ static VALUE
97
+ rb_cpSpaceSetIterations(VALUE self, VALUE val)
98
+ {
99
+ SPACE(self)->iterations = NUM2INT(val);
100
+ return val;
101
+ }
102
+
103
+ static VALUE
104
+ rb_cpSpaceGetElasticIterations(VALUE self)
105
+ {
106
+ return INT2NUM(SPACE(self)->elasticIterations);
107
+ }
108
+
109
+ static VALUE
110
+ rb_cpSpaceSetElasticIterations(VALUE self, VALUE val)
111
+ {
112
+ SPACE(self)->elasticIterations = NUM2INT(val);
113
+ return val;
114
+ }
115
+
116
+ static VALUE
117
+ rb_cpSpaceGetDamping(VALUE self)
118
+ {
119
+ return rb_float_new(SPACE(self)->damping);
120
+ }
121
+
122
+ static VALUE
123
+ rb_cpSpaceSetDamping(VALUE self, VALUE val)
124
+ {
125
+ SPACE(self)->damping = NUM2DBL(val);
126
+ return val;
127
+ }
128
+
129
+ static VALUE
130
+ rb_cpSpaceGetGravity(VALUE self)
131
+ {
132
+ return VWRAP(self, &SPACE(self)->gravity);
133
+ }
134
+
135
+ static VALUE
136
+ rb_cpSpaceSetGravity(VALUE self, VALUE val) {
137
+ SPACE(self)->gravity = *VGET(val);
138
+ return val;
139
+ }
140
+
141
+ static int
142
+ doNothingCallback(cpArbiter *arb, cpSpace *space, void *data) {
143
+ return 0;
144
+ }
145
+
146
+ // We need this as rb_obj_method_arity is not in 1.8.7
147
+ static int cp_rb_obj_method_arity(VALUE self, ID id) {
148
+ VALUE metho = rb_funcall(self , rb_intern("method"), 1, ID2SYM(id));
149
+ VALUE arity = rb_funcall(metho, rb_intern("arity"), 0, 0);
150
+ return NUM2INT(arity);
151
+ }
152
+
153
+
154
+
155
+ // This callback function centralizes all collision callbacks.
156
+ // it also adds flexibility by changing theway the callback is called on the
157
+ // arity of the callback block or method. With arity0, no args are pased,
158
+ // with arity 1, the arbiter,
159
+ // with arity 2, body_a and body_b,
160
+ // with arity 3 or more -> body_a, body_b, arbiter
161
+ static int do_callback(void * data, ID method, cpArbiter *arb) {
162
+ int res = 0;
163
+ CP_ARBITER_GET_SHAPES(arb, a, b);
164
+ VALUE object = (VALUE) data;
165
+ VALUE va = (VALUE)a->data;
166
+ VALUE vb = (VALUE)b->data;
167
+ VALUE varb = ARBWRAP(arb);
168
+ int arity = cp_rb_obj_method_arity(object, method);
169
+ switch(arity) {
170
+ case 0:
171
+ return CP_BOOL_INT(rb_funcall(object, method, 0));
172
+ case 1:
173
+ return CP_BOOL_INT(rb_funcall(object, method, 1, varb));
174
+ case 2:
175
+ return CP_BOOL_INT(rb_funcall(object, method, 2, va, vb));
176
+ case 3:
177
+ default:
178
+ return CP_BOOL_INT(rb_funcall(object, method, 3, va, vb, varb));
179
+ }
180
+ // we never get here
181
+ }
182
+
183
+
184
+ static int
185
+ compatibilityCallback(cpArbiter *arb, cpSpace *space, void *data) {
186
+ return do_callback(data, id_call, arb);
187
+ }
188
+
189
+ static int
190
+ beginCallback(cpArbiter *arb, cpSpace *space, void *data) {
191
+ return do_callback(data, id_begin, arb);
192
+ }
193
+
194
+ static int
195
+ preSolveCallback(cpArbiter *arb, cpSpace *space, void *data) {
196
+ return do_callback(data, id_pre_solve, arb);
197
+ }
198
+
199
+ static void
200
+ postSolveCallback(cpArbiter *arb, cpSpace *space, void *data) {
201
+ do_callback(data, id_post_solve, arb);
202
+ }
203
+
204
+ static void
205
+ separateCallback(cpArbiter *arb, cpSpace *space, void *data) {
206
+ do_callback(data, id_separate, arb);
207
+ }
208
+
209
+
210
+ static int
211
+ respondsTo(VALUE obj, ID method) {
212
+ VALUE value = rb_funcall(obj, rb_intern("respond_to?"), 1, ID2SYM(method));
213
+ return RTEST(value);
214
+ }
215
+
216
+ static int
217
+ isBlock(VALUE obj) {
218
+ return respondsTo(obj, id_call);
219
+ }
220
+
221
+ static VALUE
222
+ rb_cpSpaceAddCollisionHandler(int argc, VALUE *argv, VALUE self)
223
+ {
224
+ VALUE a, b, obj, block;
225
+ obj = 0;
226
+ rb_scan_args(argc, argv, "21&", &a, &b, &obj, &block);
227
+
228
+ VALUE id_a = rb_obj_id(a);
229
+ VALUE id_b = rb_obj_id(b);
230
+ VALUE blocks = rb_iv_get(self, "blocks");
231
+
232
+ if(RTEST(obj) && RTEST(block)){
233
+ rb_raise(rb_eArgError, "Cannot specify both a handler object and a block.");
234
+ } else if(RTEST(block)){
235
+ cpSpaceAddCollisionHandler(
236
+ SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b),
237
+ NULL,
238
+ compatibilityCallback,
239
+ NULL,
240
+ NULL,
241
+ (void *)block
242
+ );
243
+
244
+ rb_hash_aset(blocks, rb_ary_new3(2, id_a, id_b), block);
245
+ } else if(RTEST(obj)) {
246
+ cpSpaceAddCollisionHandler(
247
+ SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b),
248
+ (respondsTo(obj, id_begin) ? beginCallback : NULL),
249
+ (respondsTo(obj, id_pre_solve) ? preSolveCallback : NULL),
250
+ (respondsTo(obj, id_post_solve) ? postSolveCallback : NULL),
251
+ (respondsTo(obj, id_separate) ? separateCallback : NULL),
252
+ (void *)obj
253
+ );
254
+
255
+ rb_hash_aset(blocks, rb_ary_new3(2, id_a, id_b), obj);
256
+ } else {
257
+ cpSpaceAddCollisionHandler(
258
+ SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b),
259
+ NULL, doNothingCallback, NULL, NULL, NULL
260
+ );
261
+ }
262
+
263
+ return Qnil;
264
+ }
265
+
266
+ static VALUE
267
+ rb_cpSpaceRemoveCollisionHandler(VALUE self, VALUE a, VALUE b)
268
+ {
269
+ VALUE id_a = rb_obj_id(a);
270
+ VALUE id_b = rb_obj_id(b);
271
+ cpSpaceRemoveCollisionHandler(SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b));
272
+
273
+ VALUE blocks = rb_iv_get(self, "blocks");
274
+ rb_hash_delete(blocks, rb_ary_new3(2, id_a, id_b));
275
+
276
+ return Qnil;
277
+ }
278
+
279
+ static VALUE
280
+ rb_cpSpaceSetDefaultCollisionHandler(int argc, VALUE *argv, VALUE self)
281
+ {
282
+ VALUE obj, block;
283
+ rb_scan_args(argc, argv, "01&", &obj, &block);
284
+
285
+ if(RTEST(obj) && RTEST(block)){
286
+ rb_raise(rb_eArgError, "Cannot specify both a handler object and a block.");
287
+ } else if(RTEST(block)){
288
+ cpSpaceSetDefaultCollisionHandler(
289
+ SPACE(self),
290
+ NULL,
291
+ compatibilityCallback,
292
+ NULL,
293
+ NULL,
294
+ (void *)block
295
+ );
296
+
297
+ rb_hash_aset(rb_iv_get(self, "blocks"), ID2SYM(rb_intern("default")), block);
298
+ } else if(RTEST(obj)) {
299
+ cpSpaceSetDefaultCollisionHandler(
300
+ SPACE(self),
301
+ (respondsTo(obj, id_begin) ? beginCallback : NULL),
302
+ (respondsTo(obj, id_pre_solve) ? preSolveCallback : NULL),
303
+ (respondsTo(obj, id_post_solve) ? postSolveCallback : NULL),
304
+ (respondsTo(obj, id_separate) ? separateCallback : NULL),
305
+ (void *)obj
306
+ );
307
+
308
+ rb_hash_aset(rb_iv_get(self, "blocks"), ID2SYM(rb_intern("default")), obj);
309
+ } else {
310
+ cpSpaceSetDefaultCollisionHandler(
311
+ SPACE(self), NULL, doNothingCallback, NULL, NULL, NULL
312
+ );
313
+ }
314
+
315
+ return Qnil;
316
+ }
317
+
318
+ static void
319
+ poststepCallback(cpSpace *space, void *obj, void *data) {
320
+ rb_funcall((VALUE)data, id_call, 2, SPACEWRAP(space), (VALUE)obj);
321
+ }
322
+
323
+
324
+ static VALUE
325
+ rb_cpSpaceAddPostStepCallback(int argc, VALUE *argv, VALUE self) {
326
+ VALUE obj, block;
327
+ rb_scan_args(argc, argv, "10&", &obj, &block);
328
+ cpSpaceAddPostStepCallback(SPACE(self),
329
+ poststepCallback, (void *) obj, (void *) block);
330
+ return self;
331
+ }
332
+
333
+ static VALUE
334
+ rb_cpSpaceAddShape(VALUE self, VALUE shape)
335
+ {
336
+ cpSpaceAddShape(SPACE(self), SHAPE(shape));
337
+ rb_ary_push(rb_iv_get(self, "active_shapes"), shape);
338
+ return shape;
339
+ }
340
+
341
+ static VALUE
342
+ rb_cpSpaceAddStaticShape(VALUE self, VALUE shape)
343
+ {
344
+ cpSpaceAddStaticShape(SPACE(self), SHAPE(shape));
345
+ rb_ary_push(rb_iv_get(self, "static_shapes"), shape);
346
+ return shape;
347
+ }
348
+
349
+ static VALUE
350
+ rb_cpSpaceAddBody(VALUE self, VALUE body)
351
+ {
352
+ cpSpaceAddBody(SPACE(self), BODY(body));
353
+ rb_ary_push(rb_iv_get(self, "bodies"), body);
354
+ return body;
355
+ }
356
+
357
+ static VALUE
358
+ rb_cpSpaceAddConstraint(VALUE self, VALUE constraint)
359
+ {
360
+ cpSpaceAddConstraint(SPACE(self), CONSTRAINT(constraint));
361
+ rb_ary_push(rb_iv_get(self, "constraints"), constraint);
362
+ return constraint;
363
+ }
364
+
365
+ static VALUE
366
+ rb_cpSpaceRemoveShape(VALUE self, VALUE shape)
367
+ {
368
+ cpSpaceRemoveShape(SPACE(self), SHAPE(shape));
369
+ return rb_ary_delete(rb_iv_get(self, "active_shapes"), shape);
370
+ }
371
+
372
+ static VALUE
373
+ rb_cpSpaceRemoveStaticShape(VALUE self, VALUE shape)
374
+ {
375
+ cpSpaceRemoveStaticShape(SPACE(self), SHAPE(shape));
376
+ return rb_ary_delete(rb_iv_get(self, "static_shapes"), shape);
377
+ }
378
+
379
+ static VALUE
380
+ rb_cpSpaceRemoveBody(VALUE self, VALUE body)
381
+ {
382
+ cpSpaceRemoveBody(SPACE(self), BODY(body));
383
+ return rb_ary_delete(rb_iv_get(self, "bodies"), body);
384
+ }
385
+
386
+ static VALUE
387
+ rb_cpSpaceRemoveConstraint(VALUE self, VALUE constraint)
388
+ {
389
+ cpSpaceRemoveConstraint(SPACE(self), CONSTRAINT(constraint));
390
+ return rb_ary_delete(rb_iv_get(self, "constraints"), constraint);
391
+ }
392
+
393
+ static VALUE
394
+ rb_cpSpaceResizeStaticHash(VALUE self, VALUE dim, VALUE count)
395
+ {
396
+ cpSpaceResizeStaticHash(SPACE(self), NUM2DBL(dim), NUM2INT(count));
397
+ return Qnil;
398
+ }
399
+
400
+ static VALUE
401
+ rb_cpSpaceResizeActiveHash(VALUE self, VALUE dim, VALUE count)
402
+ {
403
+ cpSpaceResizeActiveHash(SPACE(self), NUM2DBL(dim), NUM2INT(count));
404
+ return Qnil;
405
+ }
406
+
407
+ static VALUE
408
+ rb_cpSpaceRehashStatic(VALUE self)
409
+ {
410
+ cpSpaceRehashStatic(SPACE(self));
411
+ return Qnil;
412
+ }
413
+
414
+ static VALUE
415
+ rb_cpSpaceRehashShape(VALUE self, VALUE shape)
416
+ {
417
+ cpSpaceRehashShape(SPACE(self), SHAPE(shape));
418
+ return Qnil;
419
+ }
420
+
421
+
422
+ static unsigned int get_layers(VALUE layers) {
423
+ if (NIL_P(layers)) return ~0;
424
+ return NUM2UINT(layers);
425
+ }
426
+
427
+ static unsigned int get_group(VALUE group) {
428
+ if (NIL_P(group)) return 0;
429
+ return NUM2UINT(group);
430
+ }
431
+
432
+ static void
433
+ pointQueryCallback(cpShape *shape, VALUE block)
434
+ {
435
+ rb_funcall(block, id_call, 1, (VALUE)shape->data);
436
+ }
437
+
438
+ static VALUE
439
+ rb_cpSpacePointQuery(int argc, VALUE *argv, VALUE self)
440
+ {
441
+ VALUE point, layers, group, block;
442
+ rb_scan_args(argc, argv, "12&", &point, &layers, &group, &block);
443
+
444
+ cpSpacePointQuery(
445
+ SPACE(self), *VGET(point), get_layers(layers), get_group(group),
446
+ (cpSpacePointQueryFunc)pointQueryCallback, (void *)block
447
+ );
448
+
449
+ return Qnil;
450
+ }
451
+
452
+ static VALUE
453
+ rb_cpSpacePointQueryFirst(int argc, VALUE *argv, VALUE self)
454
+ {
455
+ VALUE point, layers, group;
456
+ rb_scan_args(argc, argv, "12", &point, &layers, &group);
457
+
458
+ cpShape *shape = cpSpacePointQueryFirst(
459
+ SPACE(self), *VGET(point),
460
+ get_layers(layers), get_group(group)
461
+ );
462
+
463
+ return (shape ? (VALUE)shape->data : Qnil);
464
+ }
465
+
466
+ static void
467
+ segmentQueryCallback(cpShape *shape, cpFloat t, cpVect n, VALUE block)
468
+ {
469
+ rb_funcall(block, id_call, 1, (VALUE)shape->data, rb_float_new(t), VNEW(n));
470
+ }
471
+
472
+ static VALUE
473
+ rb_cpSpaceSegmentQuery(int argc, VALUE *argv, VALUE self)
474
+ {
475
+ VALUE a, b, layers, group, block;
476
+ rb_scan_args(argc, argv, "22&", &a, &b, &layers, &group, &block);
477
+
478
+ cpSpaceSegmentQuery(
479
+ SPACE(self), *VGET(a), *VGET(b),
480
+ get_layers(layers), get_group(group),
481
+ (cpSpaceSegmentQueryFunc)segmentQueryCallback, (void *)block
482
+ );
483
+
484
+ return Qnil;
485
+ }
486
+
487
+ static VALUE
488
+ rb_cpSpaceSegmentQueryFirst(int argc, VALUE *argv, VALUE self)
489
+ {
490
+ VALUE a, b, layers, group, block;
491
+ cpSegmentQueryInfo info = {NULL, 1.0f, cpvzero};
492
+
493
+ rb_scan_args(argc, argv, "22&", &a, &b, &layers, &group, &block);
494
+
495
+ cpSpaceSegmentQueryFirst(
496
+ SPACE(self), *VGET(a), *VGET(b),
497
+ get_layers(layers), get_group(group),
498
+ &info
499
+ );
500
+ // contrary to the standard chipmunk bindings, we also return a
501
+ // struct here with then needed values.
502
+ if(info.shape) {
503
+ return rb_cpSegmentQueryInfoNew((VALUE)info.shape->data, rb_float_new(info.t), VNEW(info.n));
504
+ }
505
+ return Qnil;
506
+
507
+ }
508
+
509
+
510
+ static void
511
+ bbQueryCallback(cpShape *shape, VALUE block)
512
+ {
513
+ rb_funcall(block, id_call, 1, (VALUE)shape->data);
514
+ }
515
+
516
+ /* Bounding box query. */
517
+ static VALUE
518
+ rb_cpSpaceBBQuery(int argc, VALUE *argv, VALUE self)
519
+ {
520
+ VALUE bb, layers, group, block;
521
+ unsigned int l = ~0;
522
+ unsigned int g = 0;
523
+ rb_scan_args(argc, argv, "12&", &bb, &layers, &group, &block);
524
+
525
+ if (!NIL_P(layers)) l = NUM2UINT(layers);
526
+ if (!NIL_P(group)) g = NUM2UINT(group);
527
+
528
+ cpSpaceBBQuery(
529
+ SPACE(self), *BBGET(bb), l, g,
530
+ (cpSpaceBBQueryFunc)bbQueryCallback, (void *)block
531
+ );
532
+
533
+ return Qnil;
534
+ }
535
+
536
+ static void
537
+ shapeQueryCallback(cpShape *shape, cpContactPointSet *points, VALUE block)
538
+ {
539
+ rb_funcall(block, id_call, 1, (VALUE)shape->data);
540
+ }
541
+
542
+ /* Shape query. */
543
+ static VALUE
544
+ rb_cpSpaceShapeQuery(int argc, VALUE *argv, VALUE self)
545
+ {
546
+ VALUE shape, block;
547
+ rb_scan_args(argc, argv, "1&", &shape, &block);
548
+
549
+ cpSpaceShapeQuery(
550
+ SPACE(self), SHAPE(shape),
551
+ (cpSpaceShapeQueryFunc)shapeQueryCallback, (void *)block
552
+ );
553
+
554
+ return Qnil;
555
+ }
556
+
557
+ static VALUE
558
+ rb_cpSpaceStep(VALUE self, VALUE dt)
559
+ {
560
+ cpSpaceStep(SPACE(self), NUM2DBL(dt));
561
+ return Qnil;
562
+ }
563
+
564
+ static VALUE
565
+ rb_cpSpaceGetData(VALUE self) {
566
+ return rb_iv_get(self, "data");
567
+ }
568
+
569
+ static VALUE
570
+ rb_cpSpaceSetData(VALUE self, VALUE val) {
571
+ rb_iv_set(self, "data", val);
572
+ return val;
573
+ }
574
+
575
+
576
+ static VALUE
577
+ rb_cpSpaceActivateShapesTouchingShape(VALUE self, VALUE shape)
578
+ {
579
+ cpSpaceActivateShapesTouchingShape(SPACE(self), SHAPE(shape));
580
+ return self;
581
+ }
582
+
583
+
584
+ /** in chipmunk 6
585
+ static VALUE
586
+ rb_cpSpaceUseSpatialHash(VALUE self, VALUE dim, VALUE count) {
587
+ cpSpaceUseSpatialHash(SPACE(self), NUM2DBL(dim), NUM2INT(count));
588
+ return Qnil;
589
+ }
590
+ */
591
+
592
+
593
+
594
+ void
595
+ Init_cpSpace(void)
596
+ {
597
+ id_call = rb_intern("call");
598
+ id_begin = rb_intern("begin");
599
+ id_pre_solve = rb_intern("pre_solve");
600
+ id_post_solve = rb_intern("post_solve");
601
+ id_separate = rb_intern("separate");
602
+
603
+ c_cpSpace = rb_define_class_under(m_Chipmunk, "Space", rb_cObject);
604
+ rb_define_alloc_func(c_cpSpace, rb_cpSpaceAlloc);
605
+ rb_define_method(c_cpSpace, "initialize", rb_cpSpaceInitialize, 0);
606
+
607
+ rb_define_method(c_cpSpace, "iterations", rb_cpSpaceGetIterations, 0);
608
+ rb_define_method(c_cpSpace, "iterations=", rb_cpSpaceSetIterations, 1);
609
+
610
+ rb_define_method(c_cpSpace, "elastic_iterations", rb_cpSpaceGetElasticIterations, 0);
611
+ rb_define_method(c_cpSpace, "elastic_iterations=", rb_cpSpaceSetElasticIterations, 1);
612
+
613
+ rb_define_method(c_cpSpace, "damping", rb_cpSpaceGetDamping, 0);
614
+ rb_define_method(c_cpSpace, "damping=", rb_cpSpaceSetDamping, 1);
615
+
616
+ rb_define_method(c_cpSpace, "gravity", rb_cpSpaceGetGravity, 0);
617
+ rb_define_method(c_cpSpace, "gravity=", rb_cpSpaceSetGravity, 1);
618
+
619
+ rb_define_method(c_cpSpace, "add_collision_func",
620
+ rb_cpSpaceAddCollisionHandler, -1);
621
+
622
+ rb_define_method(c_cpSpace, "add_collision_handler",
623
+ rb_cpSpaceAddCollisionHandler, -1);
624
+
625
+ rb_define_method(c_cpSpace, "on_collision",
626
+ rb_cpSpaceAddCollisionHandler, -1);
627
+
628
+ rb_define_method(c_cpSpace, "remove_collision_func",
629
+ rb_cpSpaceRemoveCollisionHandler, 2);
630
+
631
+ rb_define_method(c_cpSpace, "remove_collision_handler",
632
+ rb_cpSpaceRemoveCollisionHandler, 2);
633
+ rb_define_method(c_cpSpace, "remove_collision",
634
+ rb_cpSpaceRemoveCollisionHandler, 2);
635
+
636
+ rb_define_method(c_cpSpace, "set_default_collision_func",
637
+ rb_cpSpaceSetDefaultCollisionHandler, -1);
638
+ rb_define_method(c_cpSpace, "set_default_collision_handler",
639
+ rb_cpSpaceSetDefaultCollisionHandler, -1);
640
+ rb_define_method(c_cpSpace, "on_default_collision",
641
+ rb_cpSpaceSetDefaultCollisionHandler, -1);
642
+
643
+ rb_define_method(c_cpSpace, "add_post_step_callback",
644
+ rb_cpSpaceAddPostStepCallback, -1);
645
+ rb_define_method(c_cpSpace, "on_post_step",
646
+ rb_cpSpaceAddPostStepCallback, -1);
647
+
648
+
649
+
650
+
651
+ rb_define_method(c_cpSpace, "add_shape", rb_cpSpaceAddShape, 1);
652
+ rb_define_method(c_cpSpace, "add_static_shape", rb_cpSpaceAddStaticShape, 1);
653
+ rb_define_method(c_cpSpace, "add_body", rb_cpSpaceAddBody, 1);
654
+ rb_define_method(c_cpSpace, "add_constraint", rb_cpSpaceAddConstraint, 1);
655
+
656
+ rb_define_method(c_cpSpace, "remove_shape", rb_cpSpaceRemoveShape, 1);
657
+ rb_define_method(c_cpSpace, "remove_static_shape", rb_cpSpaceRemoveStaticShape, 1);
658
+ rb_define_method(c_cpSpace, "remove_body", rb_cpSpaceRemoveBody, 1);
659
+ rb_define_method(c_cpSpace, "remove_constraint", rb_cpSpaceRemoveConstraint, 1);
660
+
661
+ rb_define_method(c_cpSpace, "resize_static_hash", rb_cpSpaceResizeStaticHash, 2);
662
+ rb_define_method(c_cpSpace, "resize_active_hash", rb_cpSpaceResizeActiveHash, 2);
663
+ rb_define_method(c_cpSpace, "rehash_static", rb_cpSpaceRehashStatic, 0);
664
+ rb_define_method(c_cpSpace, "rehash_shape", rb_cpSpaceRehashShape, 1);
665
+
666
+ rb_define_method(c_cpSpace, "point_query", rb_cpSpacePointQuery, -1);
667
+ rb_define_method(c_cpSpace, "point_query_first", rb_cpSpacePointQueryFirst, -1);
668
+ rb_define_method(c_cpSpace, "shape_point_query", rb_cpSpacePointQueryFirst, -1);
669
+
670
+
671
+ rb_define_method(c_cpSpace, "segment_query", rb_cpSpaceSegmentQuery, -1);
672
+ rb_define_method(c_cpSpace, "segment_query_first", rb_cpSpaceSegmentQueryFirst, -1);
673
+
674
+ rb_define_method(c_cpSpace, "bb_query" , rb_cpSpaceBBQuery, -1);
675
+ rb_define_method(c_cpSpace, "shape_query" , rb_cpSpaceShapeQuery, -1);
676
+
677
+
678
+ rb_define_method(c_cpSpace, "step", rb_cpSpaceStep, 1);
679
+
680
+ rb_define_method(c_cpSpace, "object" , rb_cpSpaceGetData, 0);
681
+ rb_define_method(c_cpSpace, "object=", rb_cpSpaceSetData, 1);
682
+
683
+ rb_define_method(c_cpSpace, "sleep_time_threshold=",
684
+ rb_cpSpaceSetSleepTimeThreshold, 1);
685
+ rb_define_method(c_cpSpace, "sleep_time_threshold",
686
+ rb_cpSpaceGetSleepTimeThreshold, 0);
687
+ rb_define_method(c_cpSpace, "idle_speed_threshold=",
688
+ rb_cpSpaceSetIdleSpeedThreshold, 1);
689
+ rb_define_method(c_cpSpace, "idle_speed_threshold",
690
+ rb_cpSpaceGetIdleSpeedThreshold, 0);
691
+
692
+ // also define slghtly less verbose API
693
+ rb_define_method(c_cpSpace, "sleep_time=",
694
+ rb_cpSpaceSetSleepTimeThreshold, 1);
695
+ rb_define_method(c_cpSpace, "sleep_time",
696
+ rb_cpSpaceGetSleepTimeThreshold, 0);
697
+ rb_define_method(c_cpSpace, "idle_speed=",
698
+ rb_cpSpaceSetIdleSpeedThreshold, 1);
699
+ rb_define_method(c_cpSpace, "idle_speed",
700
+ rb_cpSpaceGetIdleSpeedThreshold, 0);
701
+
702
+ rb_define_method(c_cpSpace, "activate_shapes_touching_shape",
703
+ rb_cpSpaceActivateShapesTouchingShape, 1);
704
+
705
+ // this is nicer, though :)
706
+ rb_define_method(c_cpSpace, "activate_touching",
707
+ rb_cpSpaceActivateShapesTouchingShape, 1);
708
+
709
+
710
+
711
+ }