chipmunk 4.1.0 → 5.2.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 (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
+ }