chipmunk 4.1.0-x86-mswin32 → 5.3.4.0-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/{ext/chipmunk/cpCollision.h → LICENSE} +4 -5
  2. data/README +67 -0
  3. data/Rakefile +76 -29
  4. data/ext/chipmunk/extconf.rb +38 -0
  5. data/ext/chipmunk/rb_chipmunk.c +162 -21
  6. data/ext/chipmunk/rb_chipmunk.h +39 -11
  7. data/ext/chipmunk/rb_cpArbiter.c +253 -0
  8. data/ext/chipmunk/rb_cpBB.c +60 -4
  9. data/ext/chipmunk/rb_cpBody.c +282 -17
  10. data/ext/chipmunk/rb_cpConstraint.c +336 -0
  11. data/ext/chipmunk/rb_cpShape.c +145 -4
  12. data/ext/chipmunk/rb_cpSpace.c +438 -57
  13. data/ext/chipmunk/rb_cpVect.c +98 -2
  14. data/lib/1.8/chipmunk.so +0 -0
  15. data/lib/1.9/chipmunk.so +0 -0
  16. data/lib/chipmunk.rb +168 -0
  17. metadata +29 -41
  18. data/ext/chipmunk/chipmunk.c +0 -69
  19. data/ext/chipmunk/chipmunk.h +0 -91
  20. data/ext/chipmunk/cpArbiter.c +0 -263
  21. data/ext/chipmunk/cpArbiter.h +0 -85
  22. data/ext/chipmunk/cpArray.c +0 -114
  23. data/ext/chipmunk/cpArray.h +0 -45
  24. data/ext/chipmunk/cpBB.c +0 -46
  25. data/ext/chipmunk/cpBB.h +0 -53
  26. data/ext/chipmunk/cpBody.c +0 -180
  27. data/ext/chipmunk/cpBody.h +0 -132
  28. data/ext/chipmunk/cpCollision.c +0 -390
  29. data/ext/chipmunk/cpHashSet.c +0 -219
  30. data/ext/chipmunk/cpHashSet.h +0 -79
  31. data/ext/chipmunk/cpJoint.c +0 -553
  32. data/ext/chipmunk/cpJoint.h +0 -122
  33. data/ext/chipmunk/cpPolyShape.c +0 -139
  34. data/ext/chipmunk/cpPolyShape.h +0 -92
  35. data/ext/chipmunk/cpShape.c +0 -244
  36. data/ext/chipmunk/cpShape.h +0 -141
  37. data/ext/chipmunk/cpSpace.c +0 -530
  38. data/ext/chipmunk/cpSpace.h +0 -120
  39. data/ext/chipmunk/cpSpaceHash.c +0 -455
  40. data/ext/chipmunk/cpSpaceHash.h +0 -100
  41. data/ext/chipmunk/cpVect.c +0 -63
  42. data/ext/chipmunk/cpVect.h +0 -106
  43. data/ext/chipmunk/prime.h +0 -68
  44. data/ext/chipmunk/rb_cpJoint.c +0 -136
@@ -28,8 +28,11 @@ extern VALUE m_cpShape;
28
28
  extern VALUE c_cpCircleShape;
29
29
  extern VALUE c_cpSegmentShape;
30
30
  extern VALUE c_cpPolyShape;
31
- extern VALUE m_cpJoint;
31
+ extern VALUE m_cpConstraint;
32
32
  extern VALUE c_cpSpace;
33
+ extern VALUE c_cpArbiter;
34
+ extern VALUE c_cpStaticBody;
35
+ extern VALUE c_cpSegmentQueryInfo;
33
36
 
34
37
  extern ID id_parent;
35
38
 
@@ -50,28 +53,53 @@ VWRAP(VALUE parent, cpVect *v)
50
53
  return vec_obj;
51
54
  }
52
55
 
53
- #define GETTER_TEMPLATE(func_name, klass, klass_name, type)\
56
+ #define GETTER_TEMPLATE(func_name, klass, type)\
54
57
  static inline type *\
55
58
  func_name(VALUE self)\
56
59
  {\
57
- if(!rb_obj_is_kind_of(self, klass))\
58
- rb_raise(rb_eTypeError, "wrong argument type %s (expected CP::klass_name)", rb_obj_classname(self));\
60
+ if(!rb_obj_is_kind_of(self, klass)){\
61
+ VALUE klass_name = rb_funcall(klass, rb_intern("to_s"), 0);\
62
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", rb_obj_classname(self), StringValuePtr(klass_name));\
63
+ }\
59
64
  type *ptr;\
60
65
  Data_Get_Struct(self, type, ptr);\
61
66
  return ptr;\
62
67
  }\
63
68
 
64
- GETTER_TEMPLATE(VGET , c_cpVect , Vec2 , cpVect )
65
- GETTER_TEMPLATE(BBGET, c_cpBB , BB , cpBB )
66
- GETTER_TEMPLATE(BODY , c_cpBody , Body , cpBody )
67
- GETTER_TEMPLATE(SHAPE, m_cpShape, Shape, cpShape)
68
- GETTER_TEMPLATE(JOINT, m_cpJoint, Joint, cpJoint)
69
- GETTER_TEMPLATE(SPACE, c_cpSpace, Space, cpSpace)
69
+ GETTER_TEMPLATE(VGET , c_cpVect , cpVect )
70
+ GETTER_TEMPLATE(BBGET, c_cpBB , cpBB )
71
+ GETTER_TEMPLATE(BODY , c_cpBody , cpBody )
72
+ GETTER_TEMPLATE(STATICBODY , c_cpStaticBody , cpBody)
73
+ GETTER_TEMPLATE(SHAPE, m_cpShape, cpShape)
74
+ GETTER_TEMPLATE(CONSTRAINT, m_cpConstraint, cpConstraint)
75
+ GETTER_TEMPLATE(SPACE, c_cpSpace, cpSpace)
76
+ GETTER_TEMPLATE(ARBITER, c_cpArbiter, cpArbiter)
77
+ /* GETTER_TEMPLATE(SPACEHASH, c_cpSpaceHash, cpSpaceHash) */
78
+
79
+ // Helper to wrap cpArbter objects.
80
+ VALUE ARBWRAP(cpArbiter *arb);
81
+
82
+ //Helper that allocates and initializes a SegmenQueryInfo struct
83
+ VALUE rb_cpSegmentQueryInfoNew(VALUE shape, VALUE t, VALUE n);
70
84
 
71
85
  void Init_chipmunk(void);
72
86
  void Init_cpVect();
73
87
  void Init_cpBB();
74
88
  void Init_cpBody();
75
89
  void Init_cpShape();
76
- void Init_cpJoint();
90
+ void Init_cpConstraint();
77
91
  void Init_cpSpace();
92
+ void Init_cpArbiter(void);
93
+
94
+ // transforms a boolean VALUE to an int
95
+ #define CP_BOOL_INT(VAL) (((VAL) == Qnil) || ((VAL) == Qfalse) ? 0 : 1)
96
+
97
+ // transforms a C value (pointer or int) to Qtrue of Qfalse
98
+ // For consistency with RBH_BOOL_INT.
99
+ #define CP_INT_BOOL(VAL) ((VAL) ? Qtrue : Qfalse)
100
+
101
+
102
+
103
+
104
+
105
+
@@ -0,0 +1,253 @@
1
+ /* Copyright (c) 2010 Beoran (beoran@rubyforge.org)
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to deal
5
+ * in the Software without restriction, including without limitation the rights
6
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ * copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ * SOFTWARE.
20
+ */
21
+
22
+ #include <stdlib.h>
23
+ #include "chipmunk.h"
24
+
25
+ #include "ruby.h"
26
+ #include "rb_chipmunk.h"
27
+
28
+ VALUE c_cpArbiter;
29
+
30
+ /*
31
+ * I quote the C docs on cpArbiter:
32
+ * Memory Management
33
+ * You should never need to create an arbiter, nor will you ever need to free
34
+ * one as they are handled by the space. More importantly, because they are
35
+ * handled by the space you should never hold onto a reference to an arbiter as
36
+ * you don't know when they will be destroyed. Use them within the callback
37
+ * where they are given to you and then forget about them or copy out the
38
+ * information you need from them.
39
+ *
40
+ * This means that Arbiter doesn't need an initialize, and also
41
+ * does NOT need any garbage collection.
42
+ */
43
+
44
+ VALUE ARBWRAP(cpArbiter *arb)
45
+ {
46
+ return Data_Wrap_Struct(c_cpArbiter, NULL, NULL, arb);
47
+ }
48
+
49
+
50
+ /*
51
+ static VALUE
52
+ rb_cpArbiterAlloc(VALUE klass)
53
+ {
54
+ cpArbiter *arb = cpArbiterAlloc();
55
+ return Data_Wrap_Struct(klass, NULL, cpArbiterFree, arb);
56
+ }
57
+
58
+
59
+ static VALUE
60
+ rb_cpArbiterInitialize(VALUE self, VALUE a, VALUE b, VALUE r, VALUE t)
61
+ {
62
+ cpArbiter *arb = ARBITER(self);
63
+ cpShape *sa = SHAPE(a);
64
+ cpShape *sb = SHAPE(b);
65
+ cpArbiterInit(arb, sa, sb);
66
+ return self;
67
+ }
68
+ */
69
+
70
+ static VALUE
71
+ rb_cpArbiterTotalImpulse(VALUE self) {
72
+ cpArbiter *arb = ARBITER(self);
73
+ return VNEW(cpArbiterTotalImpulse(arb));
74
+ }
75
+
76
+ static VALUE
77
+ rb_cpArbiterTotalImpulseWithFriction(VALUE self) {
78
+ cpArbiter *arb = ARBITER(self);
79
+ return VNEW(cpArbiterTotalImpulseWithFriction(arb));
80
+ }
81
+
82
+ static VALUE
83
+ rb_cpArbiterGetImpulse(int argc, VALUE *argv, VALUE self)
84
+ {
85
+ VALUE friction = Qnil;
86
+ rb_scan_args(argc, argv, "01", &friction);
87
+ if (NIL_P(friction) || friction == Qnil) {
88
+ return rb_cpArbiterTotalImpulse(self);
89
+ }
90
+ /* Here, it's with friction */
91
+ return rb_cpArbiterTotalImpulseWithFriction(self);
92
+ }
93
+
94
+
95
+ static VALUE
96
+ rb_cpArbiterIgnore(VALUE self) {
97
+ cpArbiter *arb = ARBITER(self);
98
+ cpArbiterIgnore(arb);
99
+ return Qnil;
100
+ }
101
+
102
+ static VALUE
103
+ rb_cpArbiterGetShapes(VALUE self) {
104
+ cpArbiter *arb = ARBITER(self);
105
+ CP_ARBITER_GET_SHAPES(arb, a, b)
106
+ return rb_ary_new3(2, (VALUE)a->data, (VALUE)b->data);
107
+ }
108
+
109
+ static VALUE
110
+ rb_cpArbiterGetA(VALUE self) {
111
+ cpArbiter *arb = ARBITER(self);
112
+ CP_ARBITER_GET_SHAPES(arb, a, b)
113
+ return (VALUE)a->data;
114
+ }
115
+
116
+ static VALUE
117
+ rb_cpArbiterGetB(VALUE self) {
118
+ cpArbiter *arb = ARBITER(self);
119
+ CP_ARBITER_GET_SHAPES(arb, a, b)
120
+ return (VALUE)b->data;
121
+ }
122
+
123
+ static VALUE
124
+ rb_cpArbiterGetE(VALUE self) {
125
+ return rb_float_new(ARBITER(self)->e);
126
+ }
127
+
128
+ static VALUE
129
+ rb_cpArbiterSetE(VALUE self, VALUE e) {
130
+ ARBITER(self)->e = NUM2DBL(e);
131
+ return e;
132
+ }
133
+
134
+ static VALUE
135
+ rb_cpArbiterGetCount(VALUE self) {
136
+ return INT2NUM(cpArbiterGetCount(ARBITER(self)));
137
+ }
138
+
139
+ static VALUE
140
+ rb_cpArbiterGetU(VALUE self) {
141
+ return rb_float_new(ARBITER(self)->u);
142
+ }
143
+
144
+ static VALUE
145
+ rb_cpArbiterSetU(VALUE self, VALUE u) {
146
+ ARBITER(self)->u = NUM2DBL(u);
147
+ return u;
148
+ }
149
+
150
+ static VALUE
151
+ rb_cpArbiterIsFirstContact(VALUE self) {
152
+ int bool = cpArbiterIsFirstContact(ARBITER(self));
153
+ return bool ? Qtrue : Qfalse;
154
+ }
155
+
156
+ static int arbiterBadIndex(cpArbiter *arb, int i) {
157
+ return ((i<0) || (i >= cpArbiterGetCount(arb)));
158
+ }
159
+
160
+
161
+ static VALUE
162
+ rb_cpArbiterGetNormal(VALUE self, VALUE index) {
163
+ cpArbiter *arb = ARBITER(self);
164
+ int i = NUM2LONG(index);
165
+ if (arbiterBadIndex(arb, i)) {
166
+ rb_raise(rb_eIndexError, "No such normal.");
167
+ }
168
+ return VNEW(cpArbiterGetNormal(arb, i));
169
+ }
170
+
171
+ static VALUE
172
+ rb_cpArbiterGetPoint(VALUE self, VALUE index) {
173
+ cpArbiter *arb = ARBITER(self);
174
+ int i = NUM2LONG(index);
175
+ if (arbiterBadIndex(arb, i)) {
176
+ rb_raise(rb_eIndexError, "No such contact point.");
177
+ }
178
+ return VNEW(cpArbiterGetPoint(arb, i));
179
+ }
180
+
181
+ static VALUE
182
+ rb_cpArbiterGetDepth(VALUE self, VALUE index) {
183
+ cpArbiter *arb = ARBITER(self);
184
+ int i = NUM2LONG(index);
185
+ if (arbiterBadIndex(arb, i)) {
186
+ rb_raise(rb_eIndexError, "No such depth.");
187
+ }
188
+ // there"s a typo in the cpArbiter.h class.
189
+ return rb_float_new(cpArbiteGetDepth(arb, i));
190
+ }
191
+
192
+
193
+ static VALUE
194
+ rb_cpArbiterToString(VALUE self)
195
+ {
196
+ char str[256];
197
+ cpArbiter *arb = ARBITER(self);
198
+ sprintf(str, "#<CP::Arbiter:%p>", arb);
199
+ return rb_str_new2(str);
200
+ }
201
+
202
+ static VALUE
203
+ rb_cpArbiterEachContact(VALUE self)
204
+ {
205
+ cpArbiter *arb = ARBITER(self);
206
+ int i = 0;
207
+ for( i = 0; i < cpArbiterGetCount(arb); i++) {
208
+ VALUE index = INT2NUM(i);
209
+ VALUE contact, normal;
210
+ normal = rb_cpArbiterGetNormal(self, index);
211
+ contact = rb_cpArbiterGetPoint(self, index);
212
+ /* Yield an array of contact and normal */
213
+ rb_yield(rb_ary_new3(2, contact, normal));
214
+ }
215
+ return self;
216
+ }
217
+
218
+
219
+
220
+ void
221
+ Init_cpArbiter(void)
222
+ {
223
+ c_cpArbiter = rb_define_class_under(m_Chipmunk, "Arbiter", rb_cObject);
224
+ /*
225
+ rb_define_alloc_func(c_cpArbiter, rb_cpArbiterAlloc);
226
+ rb_define_method(c_cpArbiter , "initialize", rb_cpArbiterInitialize, 2);
227
+ */
228
+ rb_define_method(c_cpArbiter, "a", rb_cpArbiterGetA, 0);
229
+ rb_define_method(c_cpArbiter, "b", rb_cpArbiterGetB, 0);
230
+ rb_define_method(c_cpArbiter, "e" , rb_cpArbiterGetE, 0);
231
+ rb_define_method(c_cpArbiter, "u" , rb_cpArbiterGetU, 0);
232
+ rb_define_method(c_cpArbiter, "e=", rb_cpArbiterSetE, 1);
233
+ rb_define_method(c_cpArbiter, "u=", rb_cpArbiterSetU, 1);
234
+
235
+ rb_define_method(c_cpArbiter, "point" , rb_cpArbiterGetPoint , 1);
236
+ rb_define_method(c_cpArbiter, "normal" , rb_cpArbiterGetNormal , 1);
237
+ rb_define_method(c_cpArbiter, "normal" , rb_cpArbiterGetDepth , 1);
238
+ rb_define_method(c_cpArbiter, "impulse" , rb_cpArbiterGetImpulse , -1);
239
+
240
+ rb_define_method(c_cpArbiter, "to_s", rb_cpArbiterToString, 0);
241
+
242
+ rb_define_method(c_cpArbiter, "first_contact?", rb_cpArbiterIsFirstContact, 0);
243
+ rb_define_method(c_cpArbiter, "count" , rb_cpArbiterGetCount, 0);
244
+ rb_define_method(c_cpArbiter, "contacts" , rb_cpArbiterGetCount, 0);
245
+ rb_define_method(c_cpArbiter, "size" , rb_cpArbiterGetCount, 0);
246
+ rb_define_method(c_cpArbiter, "length" , rb_cpArbiterGetCount, 0);
247
+ rb_define_method(c_cpArbiter, "each_contact" , rb_cpArbiterEachContact , 0);
248
+
249
+ rb_define_method(c_cpArbiter, "shapes" , rb_cpArbiterGetShapes , 0);
250
+ /* Ignore is new in the 5.x API, I think. */
251
+ rb_define_method(c_cpArbiter, "ignore" , rb_cpArbiterIgnore , 0);
252
+
253
+ }
@@ -18,7 +18,8 @@
18
18
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  * SOFTWARE.
20
20
  */
21
-
21
+
22
+ #include <stdlib.h>
22
23
  #include "chipmunk.h"
23
24
 
24
25
  #include "ruby.h"
@@ -26,6 +27,12 @@
26
27
 
27
28
  VALUE c_cpBB;
28
29
 
30
+ static VALUE BBNEW(cpBB bb) {
31
+ cpBB *ptr = malloc(sizeof(cpBB));
32
+ *ptr = bb;
33
+ return Data_Wrap_Struct(c_cpBB, NULL, free, ptr);
34
+ }
35
+
29
36
  static VALUE
30
37
  rb_cpBBAlloc(VALUE klass)
31
38
  {
@@ -48,8 +55,34 @@ rb_cpBBInitialize(VALUE self, VALUE l, VALUE b, VALUE r, VALUE t)
48
55
  static VALUE
49
56
  rb_cpBBintersects(VALUE self, VALUE other)
50
57
  {
51
- int bool = cpBBintersects(*BBGET(self), *BBGET(other));
52
- return bool ? Qtrue : Qfalse;
58
+ int value = cpBBintersects(*BBGET(self), *BBGET(other));
59
+ return value ? Qtrue : Qfalse;
60
+ }
61
+
62
+ static VALUE
63
+ rb_cpBBcontainsBB(VALUE self, VALUE other)
64
+ {
65
+ int value = cpBBcontainsBB(*BBGET(self), *BBGET(other));
66
+ return value ? Qtrue : Qfalse;
67
+ }
68
+
69
+ static VALUE
70
+ rb_cpBBcontainsVect(VALUE self, VALUE other)
71
+ {
72
+ int value = cpBBcontainsVect(*BBGET(self), *VGET(other));
73
+ return value ? Qtrue : Qfalse;
74
+ }
75
+
76
+ static VALUE
77
+ rb_cpBBcontains(VALUE self, VALUE other)
78
+ {
79
+ if (rb_class_of(other) == c_cpBB) {
80
+ return rb_cpBBcontainsBB(self, other);
81
+ } else if (rb_class_of(other) == c_cpVect) {
82
+ return rb_cpBBcontainsVect(self, other);
83
+ }
84
+ rb_raise(rb_eArgError, "contains works only with a BB or A Vect2 argument");
85
+ return Qnil;
53
86
  }
54
87
 
55
88
  static VALUE
@@ -127,6 +160,17 @@ rb_cpBBToString(VALUE self)
127
160
  return rb_str_new2(str);
128
161
  }
129
162
 
163
+ static VALUE
164
+ rb_cpBBmerge(VALUE self, VALUE other) {
165
+ return BBNEW(cpBBmerge(*BBGET(self), *BBGET(other)));
166
+ }
167
+
168
+ static VALUE
169
+ rb_cpBBexpand(VALUE self, VALUE other) {
170
+ return BBNEW(cpBBexpand(*BBGET(self), *VGET(other)));
171
+ }
172
+
173
+
130
174
  void
131
175
  Init_cpBB(void)
132
176
  {
@@ -145,10 +189,22 @@ Init_cpBB(void)
145
189
  rb_define_method(c_cpBB, "t=", rb_cpBBSetT, 1);
146
190
 
147
191
  rb_define_method(c_cpBB, "intersect?", rb_cpBBintersects, 1);
192
+ rb_define_method(c_cpBB, "intersects?", rb_cpBBintersects, 1);
148
193
  //containsBB
149
194
  //containsVect
195
+ rb_define_method(c_cpBB, "contains?", rb_cpBBcontains, 1);
196
+ rb_define_method(c_cpBB, "contain?", rb_cpBBcontains, 1);
197
+
198
+ rb_define_method(c_cpBB, "contains_bb?", rb_cpBBcontainsBB, 1);
199
+ rb_define_method(c_cpBB, "contain_bb?", rb_cpBBcontainsBB, 1);
200
+ rb_define_method(c_cpBB, "contains_vect?", rb_cpBBcontainsVect, 1);
201
+ rb_define_method(c_cpBB, "contain_vect?", rb_cpBBcontainsVect, 1);
202
+
150
203
  rb_define_method(c_cpBB, "clamp_vect", rb_cpBBClampVect, 1);
151
- rb_define_method(c_cpBB, "wrap_vect", rb_cpBBWrapVect, 1);
204
+ rb_define_method(c_cpBB, "wrap_vect" , rb_cpBBWrapVect, 1);
205
+ rb_define_method(c_cpBB, "merge" , rb_cpBBmerge, 1);
206
+ rb_define_method(c_cpBB, "expand" , rb_cpBBexpand, 1);
207
+
152
208
 
153
209
  rb_define_method(c_cpBB, "to_s", rb_cpBBToString, 0);
154
210
  }
@@ -19,17 +19,19 @@
19
19
  * SOFTWARE.
20
20
  */
21
21
 
22
+ #include <stdlib.h>
22
23
  #include "chipmunk.h"
23
24
 
24
25
  #include "ruby.h"
25
26
  #include "rb_chipmunk.h"
26
27
 
27
28
  VALUE c_cpBody;
29
+ VALUE c_cpStaticBody;
28
30
 
29
31
  static VALUE
30
32
  rb_cpBodyAlloc(VALUE klass)
31
33
  {
32
- cpBody *body = cpBodyNew(1.0f, 1.0f);
34
+ cpBody *body = cpBodyNew(1.0f, 1.0f);
33
35
  return Data_Wrap_Struct(klass, NULL, cpBodyFree, body);
34
36
  }
35
37
 
@@ -38,22 +40,57 @@ rb_cpBodyInitialize(VALUE self, VALUE m, VALUE i)
38
40
  {
39
41
  cpBody *body = BODY(self);
40
42
  cpBodyInit(body, NUM2DBL(m), NUM2DBL(i));
41
-
43
+ body->data = (void *)self;
42
44
  return self;
43
45
  }
44
46
 
47
+ static VALUE
48
+ rb_cpBodyAllocStatic(VALUE klass)
49
+ {
50
+ cpBody *body = cpBodyNewStatic();
51
+ return Data_Wrap_Struct(c_cpStaticBody, NULL, cpBodyFree, body);
52
+ }
53
+
54
+ static VALUE
55
+ rb_cpBodyInitializeStatic(VALUE self)
56
+ {
57
+ cpBody *body = STATICBODY(self);
58
+ cpBodyInitStatic(body);
59
+ body->data = (void *)self;
60
+ return self;
61
+ }
62
+
63
+ static VALUE
64
+ rb_cpStaticBodyNew(VALUE klass) {
65
+ return rb_cpBodyInitializeStatic(rb_cpBodyAllocStatic(klass));
66
+ }
67
+
68
+
45
69
  static VALUE
46
70
  rb_cpBodyGetMass(VALUE self)
47
71
  {
48
72
  return rb_float_new(BODY(self)->m);
49
73
  }
50
74
 
75
+ static VALUE
76
+ rb_cpBodyGetMassInv(VALUE self)
77
+ {
78
+ return rb_float_new(BODY(self)->m_inv);
79
+ }
80
+
51
81
  static VALUE
52
82
  rb_cpBodyGetMoment(VALUE self)
53
83
  {
54
84
  return rb_float_new(BODY(self)->i);
55
85
  }
56
86
 
87
+
88
+ static VALUE
89
+ rb_cpBodyGetMomentInv(VALUE self)
90
+ {
91
+ return rb_float_new(BODY(self)->i_inv);
92
+ }
93
+
57
94
  static VALUE
58
95
  rb_cpBodyGetPos(VALUE self)
59
96
  {
@@ -90,6 +127,19 @@ rb_cpBodyGetTorque(VALUE self)
90
127
  return rb_float_new(BODY(self)->t);
91
128
  }
92
129
 
130
+ static VALUE
131
+ rb_cpBodyGetVLimit(VALUE self)
132
+ {
133
+ return rb_float_new(BODY(self)->v_limit);
134
+ }
135
+
136
+ static VALUE
137
+ rb_cpBodyGetWLimit(VALUE self)
138
+ {
139
+ return rb_float_new(BODY(self)->w_limit);
140
+ }
141
+
142
+
93
143
  static VALUE
94
144
  rb_cpBodyGetRot(VALUE self)
95
145
  {
@@ -153,6 +203,23 @@ rb_cpBodySetTorque(VALUE self, VALUE val)
153
203
  return val;
154
204
  }
155
205
 
206
+
207
+ static VALUE
208
+ rb_cpBodySetVLimit(VALUE self, VALUE val)
209
+ {
210
+ BODY(self)->v_limit = NUM2DBL(val);
211
+ return val;
212
+ }
213
+
214
+ static VALUE
215
+ rb_cpBodySetWLimit(VALUE self, VALUE val)
216
+ {
217
+ BODY(self)->w_limit = NUM2DBL(val);
218
+ return val;
219
+ }
220
+
221
+
222
+
156
223
  static VALUE
157
224
  rb_cpBodyLocal2World(VALUE self, VALUE v)
158
225
  {
@@ -169,35 +236,178 @@ static VALUE
169
236
  rb_cpBodyResetForces(VALUE self)
170
237
  {
171
238
  cpBodyResetForces(BODY(self));
172
- return Qnil;
239
+ return self;
173
240
  }
174
241
 
175
242
  static VALUE
176
243
  rb_cpBodyApplyForce(VALUE self, VALUE f, VALUE r)
177
244
  {
178
245
  cpBodyApplyForce(BODY(self), *VGET(f), *VGET(r));
179
- return Qnil;
246
+ return self;
180
247
  }
181
248
 
182
249
  static VALUE
183
250
  rb_cpBodyApplyImpulse(VALUE self, VALUE j, VALUE r)
184
251
  {
185
252
  cpBodyApplyImpulse(BODY(self), *VGET(j), *VGET(r));
186
- return Qnil;
253
+ return self;
187
254
  }
188
255
 
189
256
  static VALUE
190
257
  rb_cpBodyUpdateVelocity(VALUE self, VALUE g, VALUE dmp, VALUE dt)
191
258
  {
192
259
  cpBodyUpdateVelocity(BODY(self), *VGET(g), NUM2DBL(dmp), NUM2DBL(dt));
193
- return Qnil;
260
+ return self;
194
261
  }
195
262
 
196
263
  static VALUE
197
264
  rb_cpBodyUpdatePosition(VALUE self, VALUE dt)
198
265
  {
199
266
  cpBodyUpdatePosition(BODY(self), NUM2DBL(dt));
200
- return Qnil;
267
+ return self;
268
+ }
269
+
270
+ static VALUE rb_cpBodyActivate(VALUE self) {
271
+ cpBodyActivate(BODY(self));
272
+ return self;
273
+ }
274
+
275
+ static cpBody * rb_cpBodySleepValidate(VALUE vbody) {
276
+ cpBody * body = BODY(vbody);
277
+ cpSpace *space = body->space;
278
+ if(!space) {
279
+ rb_raise(rb_eArgError, "Cannot put a body to sleep that has not been added to a space.");
280
+ return NULL;
281
+ }
282
+ if (cpBodyIsStatic(body) && cpBodyIsRogue(body)) {
283
+ rb_raise(rb_eArgError, "Rogue AND static bodies cannot be put to sleep.");
284
+ return NULL;
285
+ }
286
+ if(space->locked) {
287
+ rb_raise(rb_eArgError, "Bodies can not be put to sleep during a query or a call to Space#add_collision_func. Put these calls into a post-step callback using Space#add_collision_handler.");
288
+ return NULL;
289
+ }
290
+ return body;
291
+ }
292
+
293
+ static VALUE rb_cpBodySleep(VALUE self) {
294
+ cpBody * body = rb_cpBodySleepValidate(self);
295
+ cpBodySleep(body);
296
+ return self;
297
+ }
298
+
299
+ static VALUE rb_cpBodySleepWithGroup(VALUE self, VALUE vgroup) {
300
+ cpBody * group = NIL_P(vgroup) ? NULL : rb_cpBodySleepValidate(vgroup);
301
+ cpBody * body = rb_cpBodySleepValidate(self);
302
+
303
+ if (!cpBodyIsSleeping(group)) {
304
+ rb_raise(rb_eArgError, "Cannot use a non-sleeping body as a group identifier.");
305
+ }
306
+ cpBodySleepWithGroup(body, group);
307
+ return self;
308
+ }
309
+
310
+
311
+ static VALUE rb_cpBodyIsSleeping(VALUE self) {
312
+ return cpBodyIsSleeping(BODY(self)) ? Qtrue : Qfalse;
313
+ }
314
+
315
+ static VALUE rb_cpBodyIsStatic(VALUE self) {
316
+ cpBody * body = BODY(self);
317
+ cpBool stat = 0;
318
+ // cpBodyInitStatic(body);
319
+ stat = cpBodyIsStatic(body);
320
+ return stat ? Qtrue : Qfalse;
321
+ //
322
+ }
323
+
324
+ static VALUE rb_cpBodyIsRogue(VALUE self) {
325
+ return cpBodyIsRogue(BODY(self)) ? Qtrue : Qfalse;
326
+ }
327
+
328
+ ID id_velocity_func;
329
+ ID id_speed_func;
330
+
331
+ static int
332
+ respondsTo(VALUE obj, ID method) {
333
+ VALUE value = rb_funcall(obj, rb_intern("respond_to?"), 1, ID2SYM(method));
334
+ return RTEST(value);
335
+ }
336
+
337
+ /*
338
+
339
+ typedef void (*cpBodyVelocityFunc)(struct cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
340
+ typedef void (*cpBodyPositionFunc)(struct cpBody *body, cpFloat dt);
341
+ */
342
+
343
+ static void
344
+ bodyVelocityCallback(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) {
345
+ VALUE vbody = (VALUE)(body->data);
346
+ VALUE block = rb_iv_get(vbody, "velocity_func");
347
+ VALUE vgravity = VNEW(gravity);
348
+ VALUE vdamping = rb_float_new(damping);
349
+ VALUE vdt = rb_float_new(dt);
350
+ rb_funcall(block, rb_intern("call"), 4, vbody, vgravity, vdamping, vdt);
351
+ }
352
+
353
+ static VALUE
354
+ rb_cpBodySetVelocityFunc(int argc, VALUE *argv, VALUE self)
355
+ {
356
+ VALUE block;
357
+ cpBody * body = BODY(self);
358
+ rb_scan_args(argc, argv, "&", &block);
359
+ // Restore defaults if no block
360
+ if (NIL_P(block)) {
361
+ body->velocity_func = cpBodyUpdateVelocityDefault;
362
+ return Qnil;
363
+ }
364
+ // set block for use in callback
365
+ rb_iv_set(self, "velocity_func", block);
366
+ body->velocity_func = bodyVelocityCallback;
367
+ return self;
368
+ }
369
+
370
+ static void
371
+ bodyPositionCallback(cpBody *body, cpFloat dt) {
372
+ VALUE vbody = (VALUE)(body->data);
373
+ VALUE block = rb_iv_get(vbody, "position_func");
374
+ VALUE vdt = rb_float_new(dt);
375
+ rb_funcall(block, rb_intern("call"), 2, vbody, vdt);
376
+ }
377
+
378
+ static VALUE
379
+ rb_cpBodySetPositionFunc(int argc, VALUE *argv, VALUE self)
380
+ {
381
+ VALUE block;
382
+ cpBody * body = BODY(self);
383
+ rb_scan_args(argc, argv, "&", &block);
384
+ // Restore defaults if no block
385
+ if (NIL_P(block)) {
386
+ body->velocity_func = cpBodyUpdateVelocityDefault;
387
+ return Qnil;
388
+ }
389
+ // set block for use in callback
390
+ rb_iv_set(self, "position_func", block);
391
+ body->position_func = bodyPositionCallback;
392
+ return self;
393
+ }
394
+
395
+ static VALUE
396
+ rb_cpBodyGetData(VALUE self) {
397
+ return rb_iv_get(self, "data");
398
+ }
399
+
400
+ static VALUE
401
+ rb_cpBodySetData(VALUE self, VALUE val) {
402
+ rb_iv_set(self, "data", val);
403
+ return val;
404
+ }
405
+
406
+
407
+ static VALUE
408
+ rb_cpBodySlew(VALUE self, VALUE pos, VALUE dt) {
409
+ cpBodySlew(BODY(self), *VGET(pos), NUM2DBL(dt));
410
+ return self;
201
411
  }
202
412
 
203
413
 
@@ -207,16 +417,24 @@ Init_cpBody(void)
207
417
  c_cpBody = rb_define_class_under(m_Chipmunk, "Body", rb_cObject);
208
418
  rb_define_alloc_func(c_cpBody, rb_cpBodyAlloc);
209
419
  rb_define_method(c_cpBody, "initialize", rb_cpBodyInitialize, 2);
210
-
211
- rb_define_method(c_cpBody, "m" , rb_cpBodyGetMass, 0);
212
- rb_define_method(c_cpBody, "i" , rb_cpBodyGetMoment, 0);
213
- rb_define_method(c_cpBody, "p" , rb_cpBodyGetPos, 0);
214
- rb_define_method(c_cpBody, "v" , rb_cpBodyGetVel, 0);
215
- rb_define_method(c_cpBody, "f" , rb_cpBodyGetForce, 0);
216
- rb_define_method(c_cpBody, "a" , rb_cpBodyGetAngle, 0);
217
- rb_define_method(c_cpBody, "w" , rb_cpBodyGetAVel, 0);
218
- rb_define_method(c_cpBody, "t" , rb_cpBodyGetTorque, 0);
219
- rb_define_method(c_cpBody, "rot", rb_cpBodyGetRot, 0);
420
+
421
+ c_cpStaticBody = rb_define_class_under(m_Chipmunk, "StaticBody", c_cpBody);
422
+ // rb_define_alloc_func will not work here, since superclass defines this.
423
+ // so, we define new here in stead.
424
+ rb_define_singleton_method(c_cpStaticBody, "new", rb_cpStaticBodyNew, 0);
425
+ rb_define_method(c_cpStaticBody, "initialize", rb_cpBodyInitializeStatic, 0);
426
+ rb_define_singleton_method(c_cpBody, "new_static", rb_cpStaticBodyNew, 0);
427
+
428
+ rb_define_method(c_cpBody, "m" , rb_cpBodyGetMass, 0);
429
+ rb_define_method(c_cpBody, "i" , rb_cpBodyGetMoment, 0);
430
+
431
+ rb_define_method(c_cpBody, "p" , rb_cpBodyGetPos, 0);
432
+ rb_define_method(c_cpBody, "v" , rb_cpBodyGetVel, 0);
433
+ rb_define_method(c_cpBody, "f" , rb_cpBodyGetForce, 0);
434
+ rb_define_method(c_cpBody, "a" , rb_cpBodyGetAngle, 0);
435
+ rb_define_method(c_cpBody, "w" , rb_cpBodyGetAVel, 0);
436
+ rb_define_method(c_cpBody, "t" , rb_cpBodyGetTorque, 0);
437
+ rb_define_method(c_cpBody, "rot" , rb_cpBodyGetRot, 0);
220
438
 
221
439
  rb_define_method(c_cpBody, "m=", rb_cpBodySetMass, 1);
222
440
  rb_define_method(c_cpBody, "i=", rb_cpBodySetMoment, 1);
@@ -227,6 +445,35 @@ Init_cpBody(void)
227
445
  rb_define_method(c_cpBody, "w=", rb_cpBodySetAVel, 1);
228
446
  rb_define_method(c_cpBody, "t=", rb_cpBodySetTorque, 1);
229
447
 
448
+ rb_define_method(c_cpBody, "mass" , rb_cpBodyGetMass, 0);
449
+ rb_define_method(c_cpBody, "moment" , rb_cpBodyGetMoment, 0);
450
+ rb_define_method(c_cpBody, "pos" , rb_cpBodyGetPos, 0);
451
+ rb_define_method(c_cpBody, "vel" , rb_cpBodyGetVel, 0);
452
+ rb_define_method(c_cpBody, "force" , rb_cpBodyGetForce, 0);
453
+ rb_define_method(c_cpBody, "angle" , rb_cpBodyGetAngle, 0);
454
+ rb_define_method(c_cpBody, "ang_vel" , rb_cpBodyGetAVel, 0);
455
+ rb_define_method(c_cpBody, "torque" , rb_cpBodyGetTorque, 0);
456
+ rb_define_method(c_cpBody, "rot", rb_cpBodyGetRot, 0);
457
+
458
+ rb_define_method(c_cpBody, "m_inv" , rb_cpBodyGetMassInv, 0);
459
+ rb_define_method(c_cpBody, "mass_inv" , rb_cpBodyGetMassInv, 0);
460
+ rb_define_method(c_cpBody, "moment_inv" , rb_cpBodyGetMomentInv, 0);
461
+ rb_define_method(c_cpBody, "v_limit" , rb_cpBodyGetVLimit, 0);
462
+ rb_define_method(c_cpBody, "w_limit" , rb_cpBodyGetWLimit, 0);
463
+
464
+
465
+ rb_define_method(c_cpBody, "mass=" , rb_cpBodySetMass, 1);
466
+ rb_define_method(c_cpBody, "moment=" , rb_cpBodySetMoment, 1);
467
+ rb_define_method(c_cpBody, "pos=" , rb_cpBodySetPos, 1);
468
+ rb_define_method(c_cpBody, "vel=" , rb_cpBodySetVel, 1);
469
+ rb_define_method(c_cpBody, "force=" , rb_cpBodySetForce, 1);
470
+ rb_define_method(c_cpBody, "angle=" , rb_cpBodySetAngle, 1);
471
+ rb_define_method(c_cpBody, "ang_vel=" , rb_cpBodySetAVel, 1);
472
+ rb_define_method(c_cpBody, "torque=" , rb_cpBodySetTorque, 1);
473
+ rb_define_method(c_cpBody, "v_limit=" , rb_cpBodySetVLimit, 1);
474
+ rb_define_method(c_cpBody, "w_limit=" , rb_cpBodySetWLimit, 1);
475
+
476
+
230
477
  rb_define_method(c_cpBody, "local2world", rb_cpBodyLocal2World, 1);
231
478
  rb_define_method(c_cpBody, "world2local", rb_cpBodyWorld2Local, 1);
232
479
 
@@ -236,4 +483,22 @@ Init_cpBody(void)
236
483
 
237
484
  rb_define_method(c_cpBody, "update_velocity", rb_cpBodyUpdateVelocity, 3);
238
485
  rb_define_method(c_cpBody, "update_position", rb_cpBodyUpdatePosition, 1);
486
+ rb_define_method(c_cpBody, "slew" , rb_cpBodySlew , 2);
487
+
488
+ rb_define_method(c_cpBody, "static?", rb_cpBodyIsStatic, 0);
489
+ rb_define_method(c_cpBody, "rogue?", rb_cpBodyIsRogue, 0);
490
+ rb_define_method(c_cpBody, "sleeping?", rb_cpBodyIsSleeping, 0);
491
+ rb_define_method(c_cpBody, "sleep?", rb_cpBodyIsSleeping, 0);
492
+ rb_define_method(c_cpBody, "sleep_with_self" , rb_cpBodySleep, 0);
493
+ rb_define_method(c_cpBody, "sleep_self" , rb_cpBodySleep, 0);
494
+ rb_define_method(c_cpBody, "sleep_alone" , rb_cpBodySleep, 0);
495
+ rb_define_method(c_cpBody, "sleep_with_group", rb_cpBodySleepWithGroup, 1);
496
+ rb_define_method(c_cpBody, "sleep_group" , rb_cpBodySleepWithGroup, 1);
497
+ rb_define_method(c_cpBody, "activate" , rb_cpBodyActivate , 0);
498
+ rb_define_method(c_cpBody, "velocity_func" , rb_cpBodySetVelocityFunc, -1);
499
+ rb_define_method(c_cpBody, "position_func" , rb_cpBodySetPositionFunc, -1);
500
+
501
+ rb_define_method(c_cpBody, "object=" , rb_cpBodySetData, 1);
502
+ rb_define_method(c_cpBody, "object" , rb_cpBodyGetData, 0);
503
+
239
504
  }