chipmunk 4.1.0 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/LICENSE +20 -0
  2. data/README +60 -0
  3. data/Rakefile +47 -40
  4. data/ext/chipmunk/chipmunk.c +39 -3
  5. data/ext/chipmunk/cpArbiter.c +91 -80
  6. data/ext/chipmunk/cpArray.c +24 -10
  7. data/ext/chipmunk/cpBB.c +5 -4
  8. data/ext/chipmunk/cpBody.c +30 -22
  9. data/ext/chipmunk/cpCollision.c +54 -53
  10. data/ext/chipmunk/cpConstraint.c +54 -0
  11. data/ext/chipmunk/cpDampedRotarySpring.c +106 -0
  12. data/ext/chipmunk/cpDampedSpring.c +117 -0
  13. data/ext/chipmunk/cpGearJoint.c +114 -0
  14. data/ext/chipmunk/cpGrooveJoint.c +138 -0
  15. data/ext/chipmunk/cpHashSet.c +74 -40
  16. data/ext/chipmunk/cpPinJoint.c +117 -0
  17. data/ext/chipmunk/cpPivotJoint.c +114 -0
  18. data/ext/chipmunk/cpPolyShape.c +117 -15
  19. data/ext/chipmunk/cpRatchetJoint.c +128 -0
  20. data/ext/chipmunk/cpRotaryLimitJoint.c +122 -0
  21. data/ext/chipmunk/cpShape.c +174 -18
  22. data/ext/chipmunk/cpSimpleMotor.c +99 -0
  23. data/ext/chipmunk/cpSlideJoint.c +131 -0
  24. data/ext/chipmunk/cpSpace.c +584 -215
  25. data/ext/chipmunk/cpSpaceHash.c +191 -105
  26. data/ext/chipmunk/cpVect.c +18 -10
  27. data/ext/chipmunk/extconf.rb +34 -4
  28. data/ext/chipmunk/{chipmunk.h → include/chipmunk/chipmunk.h} +63 -6
  29. data/ext/chipmunk/include/chipmunk/chipmunk_ffi.h +42 -0
  30. data/ext/chipmunk/include/chipmunk/chipmunk_types.h +80 -0
  31. data/ext/chipmunk/include/chipmunk/chipmunk_unsafe.h +54 -0
  32. data/ext/chipmunk/include/chipmunk/constraints/cpConstraint.h +92 -0
  33. data/ext/chipmunk/include/chipmunk/constraints/cpDampedRotarySpring.h +46 -0
  34. data/ext/chipmunk/include/chipmunk/constraints/cpDampedSpring.h +53 -0
  35. data/ext/chipmunk/include/chipmunk/constraints/cpGearJoint.h +41 -0
  36. data/ext/chipmunk/include/chipmunk/constraints/cpGrooveJoint.h +44 -0
  37. data/ext/chipmunk/include/chipmunk/constraints/cpPinJoint.h +43 -0
  38. data/ext/chipmunk/include/chipmunk/constraints/cpPivotJoint.h +42 -0
  39. data/ext/chipmunk/include/chipmunk/constraints/cpRatchetJoint.h +40 -0
  40. data/ext/chipmunk/include/chipmunk/constraints/cpRotaryLimitJoint.h +39 -0
  41. data/ext/chipmunk/include/chipmunk/constraints/cpSimpleMotor.h +37 -0
  42. data/ext/chipmunk/include/chipmunk/constraints/cpSlideJoint.h +44 -0
  43. data/ext/chipmunk/include/chipmunk/constraints/util.h +116 -0
  44. data/ext/chipmunk/{cpArbiter.h → include/chipmunk/cpArbiter.h} +66 -15
  45. data/ext/chipmunk/{cpArray.h → include/chipmunk/cpArray.h} +2 -1
  46. data/ext/chipmunk/{cpBB.h → include/chipmunk/cpBB.h} +21 -0
  47. data/ext/chipmunk/{cpBody.h → include/chipmunk/cpBody.h} +37 -9
  48. data/ext/chipmunk/{cpCollision.h → include/chipmunk/cpCollision.h} +1 -1
  49. data/ext/chipmunk/{cpHashSet.h → include/chipmunk/cpHashSet.h} +12 -9
  50. data/ext/chipmunk/{cpPolyShape.h → include/chipmunk/cpPolyShape.h} +13 -2
  51. data/ext/chipmunk/{cpShape.h → include/chipmunk/cpShape.h} +51 -18
  52. data/ext/chipmunk/include/chipmunk/cpSpace.h +180 -0
  53. data/ext/chipmunk/{cpSpaceHash.h → include/chipmunk/cpSpaceHash.h} +18 -9
  54. data/ext/chipmunk/{cpVect.h → include/chipmunk/cpVect.h} +61 -10
  55. data/ext/chipmunk/prime.h +32 -32
  56. data/ext/chipmunk/rb_chipmunk.c +125 -109
  57. data/ext/chipmunk/rb_chipmunk.h +96 -77
  58. data/ext/chipmunk/rb_cpArbiter.c +225 -0
  59. data/ext/chipmunk/rb_cpBB.c +174 -154
  60. data/ext/chipmunk/rb_cpBody.c +347 -239
  61. data/ext/chipmunk/rb_cpConstraint.c +346 -0
  62. data/ext/chipmunk/rb_cpShape.c +455 -292
  63. data/ext/chipmunk/rb_cpSpace.c +544 -330
  64. data/ext/chipmunk/rb_cpVect.c +321 -250
  65. data/lib/chipmunk.rb +28 -15
  66. data/lib/chipmunk/version.rb +3 -0
  67. metadata +74 -34
  68. data/ext/chipmunk/cpJoint.c +0 -553
  69. data/ext/chipmunk/cpJoint.h +0 -122
  70. data/ext/chipmunk/cpSpace.h +0 -120
  71. data/ext/chipmunk/rb_cpJoint.c +0 -136
@@ -1,330 +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 "chipmunk.h"
23
-
24
- #include "ruby.h"
25
- #include "rb_chipmunk.h"
26
-
27
- ID id_call;
28
-
29
-
30
- VALUE c_cpSpace;
31
-
32
- static VALUE
33
- rb_cpSpaceAlloc(VALUE klass)
34
- {
35
- cpSpace *space = cpSpaceAlloc();
36
- return Data_Wrap_Struct(klass, NULL, cpSpaceFree, space);
37
- }
38
-
39
- static VALUE
40
- rb_cpSpaceInitialize(VALUE self)
41
- {
42
- cpSpace *space = SPACE(self);
43
- cpSpaceInit(space);
44
-
45
- // These might as well be in one shared hash.
46
- rb_iv_set(self, "static_shapes", rb_ary_new());
47
- rb_iv_set(self, "active_shapes", rb_ary_new());
48
- rb_iv_set(self, "bodies", rb_ary_new());
49
- rb_iv_set(self, "joints", rb_ary_new());
50
- rb_iv_set(self, "blocks", rb_hash_new());
51
-
52
- return self;
53
- }
54
-
55
- static VALUE
56
- rb_cpSpaceGetIterations(VALUE self)
57
- {
58
- return INT2NUM(SPACE(self)->iterations);
59
- }
60
-
61
- static VALUE
62
- rb_cpSpaceSetIterations(VALUE self, VALUE val)
63
- {
64
- SPACE(self)->iterations = NUM2INT(val);
65
- return val;
66
- }
67
-
68
- static VALUE
69
- rb_cpSpaceGetElasticIterations(VALUE self)
70
- {
71
- return INT2NUM(SPACE(self)->elasticIterations);
72
- }
73
-
74
- static VALUE
75
- rb_cpSpaceSetElasticIterations(VALUE self, VALUE val)
76
- {
77
- SPACE(self)->elasticIterations = NUM2INT(val);
78
- return val;
79
- }
80
-
81
- static VALUE
82
- rb_cpSpaceGetDamping(VALUE self)
83
- {
84
- return rb_float_new(SPACE(self)->damping);
85
- }
86
-
87
- static VALUE
88
- rb_cpSpaceSetDamping(VALUE self, VALUE val)
89
- {
90
- SPACE(self)->damping = NUM2DBL(val);
91
- return val;
92
- }
93
-
94
- static VALUE
95
- rb_cpSpaceGetGravity(VALUE self)
96
- {
97
- return VWRAP(self, &SPACE(self)->gravity);
98
- }
99
-
100
- static VALUE
101
- rb_cpSpaceSetGravity(VALUE self, VALUE val)
102
- {
103
- SPACE(self)->gravity = *VGET(val);
104
- return val;
105
- }
106
-
107
- static int
108
- collisionCallback(cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data)
109
- {
110
- VALUE block = (VALUE)data;
111
- VALUE shapea = (VALUE)a->data;
112
- VALUE shapeb = (VALUE)b->data;
113
-
114
- return rb_funcall(block, id_call, 2, shapea, shapeb);
115
- }
116
-
117
- static VALUE
118
- rb_cpSpaceAddCollisionFunc(int argc, VALUE *argv, VALUE self)
119
- {
120
- VALUE a, b, block;
121
- rb_scan_args(argc, argv, "20&", &a, &b, &block);
122
-
123
- VALUE id_a = rb_obj_id(a);
124
- VALUE id_b = rb_obj_id(b);
125
- if(NIL_P(block)) {
126
- cpSpaceAddCollisionPairFunc(SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b),
127
- NULL, NULL);
128
- } else {
129
- cpSpaceAddCollisionPairFunc(SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b),
130
- collisionCallback, (void *)block);
131
- }
132
-
133
- VALUE blocks = rb_iv_get(self, "blocks");
134
- rb_hash_aset(blocks, rb_ary_new3(2, id_a, id_b), block);
135
-
136
- return Qnil;
137
- }
138
-
139
- static VALUE
140
- rb_cpSpaceRemoveCollisionFunc(VALUE self, VALUE a, VALUE b)
141
- {
142
- VALUE id_a = rb_obj_id(a);
143
- VALUE id_b = rb_obj_id(b);
144
- cpSpaceRemoveCollisionPairFunc(SPACE(self), NUM2UINT(id_a), NUM2UINT(id_b));
145
-
146
- VALUE blocks = rb_iv_get(self, "blocks");
147
- rb_hash_delete(blocks, rb_ary_new3(2, id_a, id_b));
148
-
149
- return Qnil;
150
- }
151
-
152
- static VALUE
153
- rb_cpSpaceSetDefaultCollisionFunc(int argc, VALUE *argv, VALUE self)
154
- {
155
- VALUE block;
156
- rb_scan_args(argc, argv, "00&", &block);
157
-
158
- if(NIL_P(block)) {
159
- cpSpaceSetDefaultCollisionPairFunc(SPACE(self), NULL, NULL);
160
- } else {
161
- cpSpaceSetDefaultCollisionPairFunc(SPACE(self), collisionCallback, (void *)block);
162
- }
163
-
164
- rb_hash_aset(rb_iv_get(self, "blocks"), ID2SYM(rb_intern("default")), block);
165
-
166
- return Qnil;
167
- }
168
-
169
- static VALUE
170
- rb_cpSpaceAddShape(VALUE self, VALUE shape)
171
- {
172
- cpSpaceAddShape(SPACE(self), SHAPE(shape));
173
- rb_ary_push(rb_iv_get(self, "active_shapes"), shape);
174
- return shape;
175
- }
176
-
177
- static VALUE
178
- rb_cpSpaceAddStaticShape(VALUE self, VALUE shape)
179
- {
180
- cpSpaceAddStaticShape(SPACE(self), SHAPE(shape));
181
- rb_ary_push(rb_iv_get(self, "static_shapes"), shape);
182
- return shape;
183
- }
184
-
185
- static VALUE
186
- rb_cpSpaceAddBody(VALUE self, VALUE body)
187
- {
188
- cpSpaceAddBody(SPACE(self), BODY(body));
189
- rb_ary_push(rb_iv_get(self, "bodies"), body);
190
- return body;
191
- }
192
-
193
- static VALUE
194
- rb_cpSpaceAddJoint(VALUE self, VALUE joint)
195
- {
196
- cpSpaceAddJoint(SPACE(self), JOINT(joint));
197
- rb_ary_push(rb_iv_get(self, "joints"), joint);
198
- return joint;
199
- }
200
-
201
- static VALUE
202
- rb_cpSpaceRemoveShape(VALUE self, VALUE shape)
203
- {
204
- cpSpaceRemoveShape(SPACE(self), SHAPE(shape));
205
- return rb_ary_delete(rb_iv_get(self, "active_shapes"), shape);
206
- }
207
-
208
- static VALUE
209
- rb_cpSpaceRemoveStaticShape(VALUE self, VALUE shape)
210
- {
211
- cpSpaceRemoveStaticShape(SPACE(self), SHAPE(shape));
212
- return rb_ary_delete(rb_iv_get(self, "static_shapes"), shape);
213
- }
214
-
215
- static VALUE
216
- rb_cpSpaceRemoveBody(VALUE self, VALUE body)
217
- {
218
- cpSpaceRemoveBody(SPACE(self), BODY(body));
219
- return rb_ary_delete(rb_iv_get(self, "bodies"), body);
220
- }
221
-
222
- static VALUE
223
- rb_cpSpaceRemoveJoint(VALUE self, VALUE joint)
224
- {
225
- cpSpaceRemoveJoint(SPACE(self), JOINT(joint));
226
- return rb_ary_delete(rb_iv_get(self, "joints"), joint);
227
- }
228
-
229
- static VALUE
230
- rb_cpSpaceResizeStaticHash(VALUE self, VALUE dim, VALUE count)
231
- {
232
- cpSpaceResizeStaticHash(SPACE(self), NUM2DBL(dim), NUM2INT(count));
233
- return Qnil;
234
- }
235
-
236
- static VALUE
237
- rb_cpSpaceResizeActiveHash(VALUE self, VALUE dim, VALUE count)
238
- {
239
- cpSpaceResizeActiveHash(SPACE(self), NUM2DBL(dim), NUM2INT(count));
240
- return Qnil;
241
- }
242
-
243
- static VALUE
244
- rb_cpSpaceRehashStatic(VALUE self)
245
- {
246
- cpSpaceRehashStatic(SPACE(self));
247
- return Qnil;
248
- }
249
-
250
- static void
251
- pointQueryHelper(cpShape *shape, void *block)
252
- {
253
- rb_funcall((VALUE)block, id_call, 1, (VALUE)shape->data);
254
- }
255
-
256
- static VALUE
257
- rb_cpSpaceShapePointQuery(int argc, VALUE *argv, VALUE self)
258
- {
259
- VALUE point, block;
260
- rb_scan_args(argc, argv, "10&", &point, &block);
261
-
262
- cpSpaceShapePointQuery(SPACE(self), *VGET(point), pointQueryHelper, (void *)block);
263
-
264
- return Qnil;
265
- }
266
-
267
- static VALUE
268
- rb_cpSpaceStaticShapePointQuery(int argc, VALUE *argv, VALUE self)
269
- {
270
- VALUE point, block;
271
- rb_scan_args(argc, argv, "10&", &point, &block);
272
-
273
- cpSpaceStaticShapePointQuery(SPACE(self), *VGET(point), pointQueryHelper, (void *)block);
274
-
275
- return Qnil;
276
- }
277
-
278
- static VALUE
279
- rb_cpSpaceStep(VALUE self, VALUE dt)
280
- {
281
- cpSpaceStep(SPACE(self), NUM2DBL(dt));
282
- return Qnil;
283
- }
284
-
285
-
286
-
287
- void
288
- Init_cpSpace(void)
289
- {
290
- id_call = rb_intern("call");
291
-
292
- c_cpSpace = rb_define_class_under(m_Chipmunk, "Space", rb_cObject);
293
- rb_define_alloc_func(c_cpSpace, rb_cpSpaceAlloc);
294
- rb_define_method(c_cpSpace, "initialize", rb_cpSpaceInitialize, 0);
295
-
296
- rb_define_method(c_cpSpace, "iterations", rb_cpSpaceGetIterations, 0);
297
- rb_define_method(c_cpSpace, "iterations=", rb_cpSpaceSetIterations, 1);
298
-
299
- rb_define_method(c_cpSpace, "elastic_iterations", rb_cpSpaceGetElasticIterations, 0);
300
- rb_define_method(c_cpSpace, "elastic_iterations=", rb_cpSpaceSetElasticIterations, 1);
301
-
302
- rb_define_method(c_cpSpace, "damping", rb_cpSpaceGetDamping, 0);
303
- rb_define_method(c_cpSpace, "damping=", rb_cpSpaceSetDamping, 1);
304
-
305
- rb_define_method(c_cpSpace, "gravity", rb_cpSpaceGetGravity, 0);
306
- rb_define_method(c_cpSpace, "gravity=", rb_cpSpaceSetGravity, 1);
307
-
308
- rb_define_method(c_cpSpace, "add_collision_func", rb_cpSpaceAddCollisionFunc, -1);
309
- rb_define_method(c_cpSpace, "remove_collision_func", rb_cpSpaceRemoveCollisionFunc, 2);
310
- rb_define_method(c_cpSpace, "set_default_collision_func", rb_cpSpaceSetDefaultCollisionFunc, -1);
311
-
312
- rb_define_method(c_cpSpace, "add_shape", rb_cpSpaceAddShape, 1);
313
- rb_define_method(c_cpSpace, "add_static_shape", rb_cpSpaceAddStaticShape, 1);
314
- rb_define_method(c_cpSpace, "add_body", rb_cpSpaceAddBody, 1);
315
- rb_define_method(c_cpSpace, "add_joint", rb_cpSpaceAddJoint, 1);
316
-
317
- rb_define_method(c_cpSpace, "remove_shape", rb_cpSpaceRemoveShape, 1);
318
- rb_define_method(c_cpSpace, "remove_static_shape", rb_cpSpaceRemoveStaticShape, 1);
319
- rb_define_method(c_cpSpace, "remove_body", rb_cpSpaceRemoveBody, 1);
320
- rb_define_method(c_cpSpace, "remove_joint", rb_cpSpaceRemoveJoint, 1);
321
-
322
- rb_define_method(c_cpSpace, "resize_static_hash", rb_cpSpaceResizeStaticHash, 2);
323
- rb_define_method(c_cpSpace, "resize_active_hash", rb_cpSpaceResizeActiveHash, 2);
324
- rb_define_method(c_cpSpace, "rehash_static", rb_cpSpaceRehashStatic, 0);
325
-
326
- rb_define_method(c_cpSpace, "shape_point_query", rb_cpSpaceShapePointQuery, -1);
327
- rb_define_method(c_cpSpace, "static_shape_point_query", rb_cpSpaceStaticShapePointQuery, -1);
328
-
329
- rb_define_method(c_cpSpace, "step", rb_cpSpaceStep, 1);
330
- }
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
+ }