reflexion 0.4.1 → 0.5.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/reflex/application.cpp +2 -0
  3. data/.doc/ext/reflex/device.cpp +2 -1
  4. data/.doc/ext/reflex/ellipse_shape.cpp +2 -0
  5. data/.doc/ext/reflex/filter.cpp +2 -0
  6. data/.doc/ext/reflex/image_view.cpp +2 -0
  7. data/.doc/ext/reflex/line_shape.cpp +2 -0
  8. data/.doc/ext/reflex/midi.cpp +2 -1
  9. data/.doc/ext/reflex/polygon_shape.cpp +2 -0
  10. data/.doc/ext/reflex/rect_shape.cpp +2 -0
  11. data/.doc/ext/reflex/shape.cpp +1 -0
  12. data/.doc/ext/reflex/timer.cpp +1 -0
  13. data/.doc/ext/reflex/view.cpp +1 -0
  14. data/.doc/ext/reflex/window.cpp +2 -0
  15. data/CLAUDE.md +1 -1
  16. data/ChangeLog.md +23 -0
  17. data/Rakefile +3 -2
  18. data/Reflex.podspec +105 -0
  19. data/VERSION +1 -1
  20. data/ext/reflex/application.cpp +2 -0
  21. data/ext/reflex/device.cpp +2 -1
  22. data/ext/reflex/ellipse_shape.cpp +2 -0
  23. data/ext/reflex/filter.cpp +2 -0
  24. data/ext/reflex/image_view.cpp +2 -0
  25. data/ext/reflex/line_shape.cpp +2 -0
  26. data/ext/reflex/midi.cpp +2 -1
  27. data/ext/reflex/polygon_shape.cpp +2 -0
  28. data/ext/reflex/rect_shape.cpp +2 -0
  29. data/ext/reflex/shape.cpp +1 -0
  30. data/ext/reflex/timer.cpp +1 -0
  31. data/ext/reflex/view.cpp +1 -0
  32. data/ext/reflex/window.cpp +2 -0
  33. data/pod.rake +41 -0
  34. data/reflex.gemspec +3 -3
  35. data/samples/multi_window.rb +80 -0
  36. data/src/body.cpp +93 -90
  37. data/src/body.h +7 -7
  38. data/src/fixture.cpp +301 -49
  39. data/src/fixture.h +55 -10
  40. data/src/osx/app_delegate.mm +6 -4
  41. data/src/osx/native_window.mm +2 -2
  42. data/src/osx/opengl_view.mm +27 -50
  43. data/src/sdl/opengl.cpp +16 -14
  44. data/src/sdl/opengl.h +2 -2
  45. data/src/sdl/window.cpp +34 -5
  46. data/src/shape.cpp +58 -51
  47. data/src/shape.h +0 -3
  48. data/src/timer.cpp +8 -10
  49. data/src/view.cpp +4 -5
  50. data/src/win32/opengl.cpp +17 -40
  51. data/src/win32/opengl.h +0 -2
  52. data/src/win32/window.cpp +32 -15
  53. data/src/window.cpp +0 -1
  54. data/src/world.cpp +301 -128
  55. data/src/world.h +12 -21
  56. data/test/test_midi_event.rb +2 -2
  57. metadata +11 -8
data/src/world.cpp CHANGED
@@ -3,9 +3,10 @@
3
3
 
4
4
  #include <assert.h>
5
5
  #include <memory>
6
- #include <box2d/b2_draw.h>
7
- #include <box2d/b2_world.h>
8
- #include <box2d/b2_contact.h>
6
+ #include <vector>
7
+ #include <map>
8
+ #include <utility>
9
+ #include <box2d/box2d.h>
9
10
  #include "reflex/event.h"
10
11
  #include "reflex/exception.h"
11
12
  #include "shape.h"
@@ -21,20 +22,28 @@ namespace Reflex
21
22
  static constexpr double DELTA_TIME = 1. / 60.;
22
23
 
23
24
 
24
- class DebugDraw : public b2Draw
25
+ class DebugDraw
25
26
  {
26
27
 
27
28
  public:
28
29
 
29
30
  DebugDraw (float ppm)
30
- : ppm(ppm), painter(NULL)
31
+ : ppm(ppm)
31
32
  {
32
- SetFlags(
33
- e_shapeBit |
34
- e_jointBit |
35
- //e_aabbBit |
36
- e_pairBit |
37
- e_centerOfMassBit);
33
+ b2draw = b2DefaultDebugDraw();
34
+ b2draw.DrawPolygonFcn = DrawPolygon;
35
+ b2draw.DrawSolidPolygonFcn = DrawSolidPolygon;
36
+ b2draw.DrawCircleFcn = DrawCircle;
37
+ b2draw.DrawSolidCircleFcn = DrawSolidCircle;
38
+ b2draw.DrawSolidCapsuleFcn = DrawSolidCapsule;
39
+ b2draw.DrawSegmentFcn = DrawSegment;
40
+ b2draw.DrawTransformFcn = DrawTransform;
41
+ b2draw.DrawPointFcn = DrawPoint;
42
+ b2draw.DrawStringFcn = DrawString;
43
+ b2draw.drawShapes = true;
44
+ b2draw.drawJoints = true;
45
+ b2draw.drawMass = true;
46
+ b2draw.context = this;
38
47
  }
39
48
 
40
49
  void begin (Painter* painter)
@@ -49,101 +58,284 @@ namespace Reflex
49
58
  painter = NULL;
50
59
  }
51
60
 
52
- void DrawPolygon (
53
- const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
61
+ b2DebugDraw* b2ptr ()
54
62
  {
55
- assert(painter);
63
+ return &b2draw;
64
+ }
65
+
66
+ private:
56
67
 
57
- painter->no_fill();
58
- painter->set_stroke(color.r, color.g, color.b, color.a * 0.5);
68
+ b2DebugDraw b2draw;
69
+
70
+ float ppm;
71
+
72
+ Painter* painter = NULL;
73
+
74
+ static void set_fill (DebugDraw* draw, b2HexColor color)
75
+ {
76
+ draw->painter->set_fill(
77
+ ((color >> 16) & 0xff) / 255.f,
78
+ ((color >> 8) & 0xff) / 255.f,
79
+ ( color & 0xff) / 255.f,
80
+ 0.5f);
81
+ draw->painter->no_stroke();
82
+ }
59
83
 
84
+ static void set_stroke (DebugDraw* draw, b2HexColor color)
85
+ {
86
+ draw->painter->no_fill();
87
+ draw->painter->set_stroke(
88
+ ((color >> 16) & 0xff) / 255.f,
89
+ ((color >> 8) & 0xff) / 255.f,
90
+ ( color & 0xff) / 255.f,
91
+ 0.5f);
92
+ }
93
+
94
+ static void draw_polygon (
95
+ DebugDraw* draw, const b2Vec2* vertices, int vertexCount)
96
+ {
60
97
  std::unique_ptr<Point[]> points(new Point[vertexCount]);
61
98
  for (int i = 0; i < vertexCount; ++i)
62
- points[i] = to_point(vertices[i], ppm);
99
+ points[i] = to_point(vertices[i], draw->ppm);
63
100
 
64
- painter->line(&points[0], vertexCount, true);
101
+ draw->painter->line(&points[0], vertexCount, true);
65
102
  }
66
103
 
67
- void DrawSolidPolygon (
68
- const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
104
+ static void DrawPolygon (
105
+ const b2Vec2* vertices, int vertexCount, b2HexColor color,
106
+ void* context)
69
107
  {
70
- assert(painter);
108
+ DebugDraw* draw = (DebugDraw*) context;
109
+ assert(draw && draw->painter);
71
110
 
72
- painter->set_fill(color.r, color.g, color.b, color.a * 0.5);
73
- painter->no_stroke();
111
+ set_stroke(draw, color);
112
+ draw_polygon(draw, vertices, vertexCount);
113
+ }
74
114
 
75
- std::unique_ptr<Point[]> points(new Point[vertexCount]);
115
+ static void DrawSolidPolygon (
116
+ b2Transform transform, const b2Vec2* vertices, int vertexCount,
117
+ float radius, b2HexColor color, void* context)
118
+ {
119
+ DebugDraw* draw = (DebugDraw*) context;
120
+ assert(draw && draw->painter);
121
+
122
+ std::vector<b2Vec2> points;
123
+ points.reserve(vertexCount);
76
124
  for (int i = 0; i < vertexCount; ++i)
77
- points[i] = to_point(vertices[i], ppm);
125
+ points.emplace_back(b2TransformPoint(transform, vertices[i]));
78
126
 
79
- painter->line(&points[0], vertexCount, true);
127
+ set_fill(draw, color);
128
+ draw_polygon(draw, &points[0], vertexCount);
80
129
  }
81
130
 
82
- void DrawCircle (
83
- const b2Vec2& center, float radius, const b2Color& color)
131
+ static void DrawCircle (
132
+ b2Vec2 center, float radius, b2HexColor color, void* context)
84
133
  {
85
- assert(painter);
134
+ DebugDraw* draw = (DebugDraw*) context;
135
+ assert(draw && draw->painter);
86
136
 
87
- painter->no_fill();
88
- painter->set_stroke(color.r, color.g, color.b, color.a * 0.5);
89
- painter->ellipse(to_point(center, ppm), to_coord(radius, ppm));
137
+ set_stroke(draw, color);
138
+ draw->painter->ellipse(
139
+ to_point(center, draw->ppm), to_coord(radius, draw->ppm));
90
140
  }
91
141
 
92
- void DrawSolidCircle (
93
- const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color)
142
+ static void DrawSolidCircle (
143
+ b2Transform transform, float radius, b2HexColor color, void* context)
94
144
  {
95
- assert(painter);
145
+ DebugDraw* draw = (DebugDraw*) context;
146
+ assert(draw && draw->painter);
96
147
 
97
- painter->set_fill(color.r, color.g, color.b, color.a * 0.5);
98
- painter->no_stroke();
99
- painter->ellipse(to_point(center, ppm), to_coord(radius, ppm));
148
+ set_fill(draw, color);
149
+ draw->painter->ellipse(
150
+ to_point(transform.p, draw->ppm), to_coord(radius, draw->ppm));
100
151
  }
101
152
 
102
- void DrawSegment (
103
- const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
153
+ static void DrawSolidCapsule (
154
+ b2Vec2 p1, b2Vec2 p2, float radius, b2HexColor color, void* context)
104
155
  {
105
- assert(painter);
156
+ DebugDraw* draw = (DebugDraw*) context;
157
+ assert(draw && draw->painter);
158
+
159
+ set_fill(draw, color);
160
+ draw->painter->ellipse(
161
+ to_point(p1, draw->ppm), to_coord(radius, draw->ppm));
162
+ draw->painter->ellipse(
163
+ to_point(p2, draw->ppm), to_coord(radius, draw->ppm));
164
+ draw->painter->line(
165
+ to_point(p1, draw->ppm), to_point(p2, draw->ppm));
166
+ }
167
+
168
+ static void DrawSegment (
169
+ b2Vec2 p1, b2Vec2 p2, b2HexColor color, void* context)
170
+ {
171
+ DebugDraw* draw = (DebugDraw*) context;
172
+ assert(draw && draw->painter);
106
173
 
107
- painter->no_fill();
108
- painter->set_stroke(color.r, color.g, color.b, color.a * 0.5);
109
- painter->line(to_point(p1, ppm), to_point(p2, ppm));
174
+ set_stroke(draw, color);
175
+ draw->painter->line(
176
+ to_point(p1, draw->ppm), to_point(p2, draw->ppm));
110
177
  }
111
178
 
112
- void DrawPoint (const b2Vec2& center, float size, const b2Color& color)
179
+ static void DrawPoint (
180
+ b2Vec2 p, float size, b2HexColor color, void* context)
113
181
  {
114
- assert(painter);
182
+ DebugDraw* draw = (DebugDraw*) context;
183
+ assert(draw && draw->painter);
115
184
 
116
- painter->set_fill(color.r, color.g, color.b, color.a * 0.5);
117
- painter->no_stroke();
118
- painter->ellipse(to_point(center, ppm), to_coord(size / 2, ppm));
185
+ set_fill(draw, color);
186
+ draw->painter->ellipse(
187
+ to_point(p, draw->ppm), to_coord(size / 2, draw->ppm));
119
188
  }
120
189
 
121
- void DrawTransform (const b2Transform& transform)
190
+ static void DrawTransform (b2Transform transform, void* context)
122
191
  {
123
- assert(painter);
124
192
  }
125
193
 
126
- private:
194
+ static void DrawString (
195
+ b2Vec2 p, const char* s, b2HexColor color, void* context)
196
+ {
197
+ }
127
198
 
128
- float ppm;
199
+ };// DebugDraw
129
200
 
130
- Painter* painter;
131
201
 
132
- };// DebugDraw
202
+ typedef std::pair<uint64_t, uint64_t> ShapePairKey;
203
+
204
+ typedef std::pair<Shape*, Shape*> ShapePair;
205
+
206
+ typedef std::map<ShapePairKey, ShapePair> ShapePairMap;
207
+
208
+ static ShapePairKey
209
+ make_pair_key (b2ShapeId b2shape1, b2ShapeId b2shape2)
210
+ {
211
+ uint64_t key1 = b2StoreShapeId(b2shape1);
212
+ uint64_t key2 = b2StoreShapeId(b2shape2);
213
+ return key1 < key2
214
+ ? std::make_pair(key1, key2)
215
+ : std::make_pair(key2, key1);
216
+ }
217
+
218
+ static Shape*
219
+ get_shape (b2ShapeId b2shape)
220
+ {
221
+ if (B2_IS_NULL(b2shape)) return NULL;
222
+ return (Shape*) b2Shape_GetUserData(b2shape);
223
+ }
224
+
225
+ static bool
226
+ should_collide (Shape* s1, Shape* s2)
227
+ {
228
+ if (!s1 || !s2)
229
+ return false;
230
+
231
+ View* v1 = s1->owner();
232
+ View* v2 = s2->owner();
233
+ if (!v1 || !v2 || !View_is_active(*v1) || !View_is_active(*v2))
234
+ return false;
235
+
236
+ return
237
+ s1->will_contact(s2) &&
238
+ s2->will_contact(s1) &&
239
+ v1->will_contact(v2) &&
240
+ v2->will_contact(v1);
241
+ }
242
+
243
+ static bool
244
+ custom_filter_callback (b2ShapeId b2shape1, b2ShapeId b2shape2, void* context)
245
+ {
246
+ return should_collide(get_shape(b2shape1), get_shape(b2shape2));
247
+ }
248
+
249
+ static void
250
+ call_contact_events (Shape* s1, Shape* s2, ContactEvent::Action action)
251
+ {
252
+ if (!s1 || !s2)
253
+ return;
254
+
255
+ View* v1 = s1->owner();
256
+ View* v2 = s2->owner();
257
+ if (!v1 || !v2 || !View_is_active(*v1) || !View_is_active(*v2))
258
+ return;
259
+
260
+ ContactEvent e1(action, s2), e2(action, s1);
261
+ Shape_call_contact_event(s1, &e1);
262
+ Shape_call_contact_event(s2, &e2);
263
+ }
133
264
 
134
265
 
135
266
  struct World::Data
136
267
  {
137
268
 
138
- b2World b2world;
269
+ b2WorldId b2world = b2_nullWorldId;
270
+
271
+ float ppm = 0;
272
+
273
+ float time_scale = 1;
139
274
 
140
- float ppm, time_scale;
275
+ bool stepping = false;
141
276
 
142
277
  std::unique_ptr<DebugDraw> debug_draw;
143
278
 
144
- Data ()
145
- : b2world(b2Vec2(0, 0)), ppm(0), time_scale(1)
279
+ // tracked to deliver contact-end events for shapes that Box2D has already
280
+ // forgotten on destruction
281
+ ShapePairMap touching_pairs;
282
+
283
+ void begin_contact (b2ShapeId b2shape1, b2ShapeId b2shape2, bool is_sensor_event)
146
284
  {
285
+ Shape* s1 = get_shape(b2shape1);
286
+ Shape* s2 = get_shape(b2shape2);
287
+ if (!s1 || !s2)
288
+ return;
289
+
290
+ // Box2D 3.x does not call the custom filter for sensor overlaps,
291
+ // so respect will_contact() here
292
+ if (is_sensor_event && !should_collide(s1, s2))
293
+ return;
294
+
295
+ ShapePairKey key = make_pair_key(b2shape1, b2shape2);
296
+ if (!touching_pairs.emplace(key, ShapePair(s1, s2)).second)
297
+ return;// already touching
298
+
299
+ call_contact_events(s1, s2, ContactEvent::BEGIN);
300
+ }
301
+
302
+ void end_contact (b2ShapeId id1, b2ShapeId id2)
303
+ {
304
+ auto it = touching_pairs.find(make_pair_key(id1, id2));
305
+ if (it == touching_pairs.end())
306
+ return;
307
+
308
+ ShapePair pair = it->second;
309
+ touching_pairs.erase(it);
310
+
311
+ call_contact_events(pair.first, pair.second, ContactEvent::END);
312
+ }
313
+
314
+ void handle_contact_events ()
315
+ {
316
+ b2ContactEvents contacts = b2World_GetContactEvents(b2world);
317
+ for (int i = 0; i < contacts.beginCount; ++i)
318
+ {
319
+ const auto& e = contacts.beginEvents[i];
320
+ begin_contact(e.shapeIdA, e.shapeIdB, false);
321
+ }
322
+ for (int i = 0; i < contacts.endCount; ++i)
323
+ {
324
+ const auto& e = contacts.endEvents[i];
325
+ end_contact(e.shapeIdA, e.shapeIdB);
326
+ }
327
+
328
+ b2SensorEvents sensors = b2World_GetSensorEvents(b2world);
329
+ for (int i = 0; i < sensors.beginCount; ++i)
330
+ {
331
+ const auto& e = sensors.beginEvents[i];
332
+ begin_contact(e.sensorShapeId, e.visitorShapeId, true);
333
+ }
334
+ for (int i = 0; i < sensors.endCount; ++i)
335
+ {
336
+ const auto& e = sensors.endEvents[i];
337
+ end_contact(e.sensorShapeId, e.visitorShapeId);
338
+ }
147
339
  }
148
340
 
149
341
  };// World::Data
@@ -155,14 +347,23 @@ namespace Reflex
155
347
 
156
348
  self->ppm = pixels_per_meter;
157
349
 
158
- self->b2world.SetContactListener(this);
159
- self->b2world.SetContactFilter(this);
350
+ b2WorldDef def = b2DefaultWorldDef();
351
+ def.gravity = b2Vec2{0, 0};
352
+ def.userData = this;
353
+
354
+ self->b2world = b2CreateWorld(&def);
355
+ if (!b2World_IsValid(self->b2world))
356
+ physics_error(__FILE__, __LINE__);
357
+
358
+ b2World_SetCustomFilterCallback(self->b2world, custom_filter_callback, this);
160
359
  }
161
360
 
162
361
  World::~World ()
163
362
  {
164
- self->b2world.SetContactListener(NULL);
165
- self->b2world.SetContactFilter(NULL);
363
+ self->touching_pairs.clear();
364
+
365
+ b2DestroyWorld(self->b2world);
366
+ self->b2world = b2_nullWorldId;
166
367
  }
167
368
 
168
369
  void
@@ -175,7 +376,13 @@ namespace Reflex
175
376
  if (count < 1) count = 1;
176
377
 
177
378
  for (int i = 0; i < count; ++i)
178
- self->b2world.Step(dt, 8, 4);
379
+ {
380
+ self->stepping = true;
381
+ b2World_Step(self->b2world, dt, 4);
382
+ self->stepping = false;
383
+
384
+ self->handle_contact_events();
385
+ }
179
386
  }
180
387
 
181
388
  float
@@ -187,17 +394,18 @@ namespace Reflex
187
394
  void
188
395
  World::set_gravity (const Point& gravity)
189
396
  {
190
- b2Vec2 b2gravity = to_b2vec2(gravity, self->ppm);
191
- if (b2gravity == self->b2world.GetGravity())
397
+ b2Vec2 b2vec = to_b2vec2(gravity, self->ppm);
398
+ b2Vec2 current = b2World_GetGravity(self->b2world);
399
+ if (b2vec.x == current.x && b2vec.y == current.y)
192
400
  return;
193
401
 
194
- self->b2world.SetGravity(b2gravity);
402
+ b2World_SetGravity(self->b2world, b2vec);
195
403
  }
196
404
 
197
405
  Point
198
406
  World::gravity () const
199
407
  {
200
- return to_point(self->b2world.GetGravity(), self->ppm);
408
+ return to_point(b2World_GetGravity(self->b2world), self->ppm);
201
409
  }
202
410
 
203
411
  void
@@ -218,14 +426,9 @@ namespace Reflex
218
426
  if (state == debug()) return;
219
427
 
220
428
  if (state)
221
- {
222
- assert(!self->debug_draw);
223
429
  self->debug_draw.reset(new DebugDraw(self->ppm));
224
- }
225
430
  else
226
431
  self->debug_draw.reset();
227
-
228
- self->b2world.SetDebugDraw(self->debug_draw.get());
229
432
  }
230
433
 
231
434
  bool
@@ -246,65 +449,47 @@ namespace Reflex
246
449
  if (!self->debug_draw) return;
247
450
 
248
451
  self->debug_draw->begin(painter);
249
- self->b2world.DebugDraw();
452
+ b2World_Draw(self->b2world, self->debug_draw->b2ptr());
250
453
  self->debug_draw->end();
251
454
  }
252
455
 
253
- bool
254
- World::ShouldCollide (b2Fixture* f1, b2Fixture* f2)
255
- {
256
- Shape* s1 = (Shape*) f1->GetUserData().pointer;
257
- Shape* s2 = (Shape*) f2->GetUserData().pointer;
258
- if (!s1 || !s2)
259
- return false;
260
456
 
261
- View* v1 = s1->owner();
262
- View* v2 = s2->owner();
263
- if (!v1 || !v2 || !View_is_active(*v1) || !View_is_active(*v2))
264
- return false;
265
-
266
- return
267
- s1->will_contact(s2) &&
268
- s2->will_contact(s1) &&
269
- v1->will_contact(v2) &&
270
- v2->will_contact(v1);
457
+ b2WorldId
458
+ World_get_id (const World* world)
459
+ {
460
+ return world ? world->self->b2world : b2_nullWorldId;
271
461
  }
272
462
 
273
- void
274
- World::BeginContact (b2Contact* contact)
463
+ bool
464
+ World_is_stepping (const World* world)
275
465
  {
276
- Shape* s1 = (Shape*) contact->GetFixtureA()->GetUserData().pointer;
277
- if (!s1) return;
278
-
279
- Shape* s2 = (Shape*) contact->GetFixtureB()->GetUserData().pointer;
280
- if (!s2) return;
281
-
282
- if (!View_is_active(*s1->owner()) || !View_is_active(*s2->owner()))
283
- return;
284
-
285
- ContactEvent e1(ContactEvent::BEGIN, s2), e2(ContactEvent::BEGIN, s1);
286
- Shape_call_contact_event(s1, &e1);
287
- Shape_call_contact_event(s2, &e2);
466
+ return world ? world->self->stepping : false;
288
467
  }
289
468
 
290
469
  void
291
- World::EndContact (b2Contact* contact)
470
+ World_end_contacts_for (World* world, b2ShapeId b2shape)
292
471
  {
293
- Shape* s1 = (Shape*) contact->GetFixtureA()->GetUserData().pointer;
294
- if (!s1) return;
472
+ if (!world) return;
295
473
 
296
- Shape* s2 = (Shape*) contact->GetFixtureB()->GetUserData().pointer;
297
- if (!s2) return;
474
+ uint64_t key = b2StoreShapeId(b2shape);
298
475
 
299
- if (!View_is_active(*s1->owner()) || !View_is_active(*s2->owner()))
300
- return;
476
+ std::vector<ShapePair> ended;
477
+ auto& pairs = world->self->touching_pairs;
478
+ for (auto it = pairs.begin(); it != pairs.end();)
479
+ {
480
+ if (it->first.first == key || it->first.second == key)
481
+ {
482
+ ended.emplace_back(it->second);
483
+ it = pairs.erase(it);
484
+ }
485
+ else
486
+ ++it;
487
+ }
301
488
 
302
- ContactEvent e1(ContactEvent::END, s2), e2(ContactEvent::END, s1);
303
- Shape_call_contact_event(s1, &e1);
304
- Shape_call_contact_event(s2, &e2);
489
+ for (auto& pair : ended)
490
+ call_contact_events(pair.first, pair.second, ContactEvent::END);
305
491
  }
306
492
 
307
-
308
493
  World*
309
494
  World_get_temporary ()
310
495
  {
@@ -312,17 +497,5 @@ namespace Reflex
312
497
  return &world;
313
498
  }
314
499
 
315
- b2World*
316
- World_get_b2ptr (World* world)
317
- {
318
- return world ? &world->self->b2world : NULL;
319
- }
320
-
321
- const b2World*
322
- World_get_b2ptr (const World* world)
323
- {
324
- return World_get_b2ptr(const_cast<World*>(world));
325
- }
326
-
327
500
 
328
501
  }// Reflex
data/src/world.h CHANGED
@@ -4,8 +4,8 @@
4
4
  #define __REFLEX_SRC_WORLD_H__
5
5
 
6
6
 
7
- #include <box2d/b2_math.h>
8
- #include <box2d/b2_world_callbacks.h>
7
+ #include <box2d/id.h>
8
+ #include <box2d/math_functions.h>
9
9
  #include <xot/noncopyable.h>
10
10
  #include <xot/pimpl.h>
11
11
  #include <rays/point.h>
@@ -13,9 +13,6 @@
13
13
  #include "reflex/defs.h"
14
14
 
15
15
 
16
- class b2World;
17
-
18
-
19
16
  namespace Reflex
20
17
  {
21
18
 
@@ -24,7 +21,7 @@ namespace Reflex
24
21
  class Body;
25
22
 
26
23
 
27
- class World : public Xot::NonCopyable, private b2ContactFilter, b2ContactListener
24
+ class World : public Xot::NonCopyable
28
25
  {
29
26
 
30
27
  public:
@@ -62,14 +59,6 @@ namespace Reflex
62
59
 
63
60
  Xot::PImpl<Data> self;
64
61
 
65
- protected:
66
-
67
- virtual bool ShouldCollide (b2Fixture* f1, b2Fixture* f2) override;
68
-
69
- virtual void BeginContact (b2Contact* contact) override;
70
-
71
- virtual void EndContact (b2Contact* contact) override;
72
-
73
62
  };// World
74
63
 
75
64
 
@@ -84,18 +73,18 @@ namespace Reflex
84
73
  inline b2Vec2
85
74
  to_b2vec2 (T x, T y, float scale)
86
75
  {
87
- return b2Vec2(
76
+ return b2Vec2{
88
77
  to_b2coord(x, scale),
89
- to_b2coord(y, scale));
78
+ to_b2coord(y, scale)};
90
79
  }
91
80
 
92
81
  template <typename VEC>
93
82
  inline b2Vec2
94
83
  to_b2vec2 (const VEC& v, float scale)
95
84
  {
96
- return b2Vec2(
85
+ return b2Vec2{
97
86
  to_b2coord(v.x, scale),
98
- to_b2coord(v.y, scale));
87
+ to_b2coord(v.y, scale)};
99
88
  }
100
89
 
101
90
  inline coord
@@ -113,11 +102,13 @@ namespace Reflex
113
102
  }
114
103
 
115
104
 
116
- World* World_get_temporary ();
105
+ b2WorldId World_get_id (const World* world);
117
106
 
118
- b2World* World_get_b2ptr ( World* world);
107
+ bool World_is_stepping (const World* world);
119
108
 
120
- const b2World* World_get_b2ptr (const World* world);
109
+ void World_end_contacts_for (World* world, b2ShapeId b2shape);
110
+
111
+ World* World_get_temporary ();
121
112
 
122
113
 
123
114
  }// Reflex
@@ -86,8 +86,8 @@ class TestMIDIEvent < Test::Unit::TestCase
86
86
  assert_equal 5, event(0xC5, 1, 2, 3).channel
87
87
  assert_equal 6, event(0xD6, 1, 2, 3).channel
88
88
  assert_equal 7, event(0xE7, 1, 2, 3).channel
89
- assert_equal -1, event(0xF8, 1, 2, 3).channel
90
- assert_equal -1, event(0x00, 1, 2, 3).channel
89
+ assert_equal(-1, event(0xF8, 1, 2, 3).channel)
90
+ assert_equal(-1, event(0x00, 1, 2, 3).channel)
91
91
  end
92
92
 
93
93
  end# TestMIDIEvent