chipmunk 5.2.2 → 5.3.4.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }