diff --git a/packages/forge2d/lib/src/dynamics/world.dart b/packages/forge2d/lib/src/dynamics/world.dart
index 935a6a9..06c062c 100644
--- a/packages/forge2d/lib/src/dynamics/world.dart
+++ b/packages/forge2d/lib/src/dynamics/world.dart
@@ -25,10 +25,10 @@ class World {
late ContactManager contactManager;
final List
bodies = [];
final List joints = [];
- final List bodiesToCreate = [];
- final List bodiesToDestroy = [];
- final List jointsToCreate = [];
- final List jointsToDestroy = [];
+ final List _bodiesToCreate = [];
+ final List _bodiesToDestroy = [];
+ final List _jointsToCreate = [];
+ final List _jointsToDestroy = [];
final Vector2 _gravity;
@@ -139,7 +139,7 @@ class World {
Body createBody(BodyDef def) {
final body = Body(def, this);
if (isLocked) {
- bodiesToCreate.add(body);
+ _bodiesToCreate.add(body);
return body;
}
bodies.add(body);
@@ -153,7 +153,7 @@ class World {
/// Warning: This function is locked during callbacks.
void destroyBody(Body body) {
if (isLocked) {
- bodiesToDestroy.add(body);
+ _bodiesToDestroy.add(body);
return;
}
@@ -184,7 +184,7 @@ class World {
/// Adding a joint doesn't wake up the bodies.
void createJoint(Joint joint) {
if (isLocked) {
- jointsToCreate.add(joint);
+ _jointsToCreate.add(joint);
return;
}
joints.add(joint);
@@ -209,7 +209,7 @@ class World {
/// Destroys a joint. This may cause the connected bodies to begin colliding.
void destroyJoint(Joint joint) {
if (isLocked) {
- jointsToDestroy.add(joint);
+ _jointsToDestroy.add(joint);
return;
}
@@ -308,15 +308,25 @@ class World {
flags &= ~locked;
- for (final body in bodiesToCreate) {
+ for (final body in _bodiesToCreate) {
bodies.add(body);
}
- bodiesToCreate.clear();
+ _bodiesToCreate.clear();
- for (final body in bodiesToDestroy) {
+ for (final body in _bodiesToDestroy) {
destroyBody(body);
}
- bodiesToDestroy.clear();
+ _bodiesToDestroy.clear();
+
+ for (final joint in _jointsToCreate) {
+ createJoint(joint);
+ }
+ _jointsToCreate.clear();
+
+ for (final joint in _jointsToDestroy) {
+ destroyJoint(joint);
+ }
+ _jointsToDestroy.clear();
_profile.step.record(_stepTimer.getMilliseconds());
}
diff --git a/packages/forge2d/test/dynamics/body_test.dart b/packages/forge2d/test/dynamics/body_test.dart
index 5805eea..cb5946b 100644
--- a/packages/forge2d/test/dynamics/body_test.dart
+++ b/packages/forge2d/test/dynamics/body_test.dart
@@ -83,5 +83,34 @@ void main() {
expect(bodyInitialPosition.y, isNot(equals(body.position.y)));
});
});
+
+ test('creation and destruction of body while world is locked', () {
+ final world = World(Vector2(0.0, -10.0));
+ final bodyDef = BodyDef();
+
+ world.flags = World.locked;
+
+ // Attempt to create a body while the world is locked
+ final body = world.createBody(bodyDef);
+ expect(world.bodies.contains(body), isFalse);
+
+ world.flags = 0;
+ world.stepDt(1 / 60);
+
+ // Verify the body is created after unlocking the world
+ expect(world.bodies.contains(body), isTrue);
+
+ world.flags = World.locked;
+
+ // Attempt to destroy the body while the world is locked
+ world.destroyBody(body);
+ expect(world.bodies.contains(body), isTrue);
+
+ world.flags = 0;
+ world.stepDt(1 / 60);
+
+ // Verify the body is destroyed after unlocking the world
+ expect(world.bodies.contains(body), isFalse);
+ });
});
}
diff --git a/packages/forge2d/test/dynamics/joints/joint_test.dart b/packages/forge2d/test/dynamics/joints/joint_test.dart
index 2bb7bf1..134f3cf 100644
--- a/packages/forge2d/test/dynamics/joints/joint_test.dart
+++ b/packages/forge2d/test/dynamics/joints/joint_test.dart
@@ -39,5 +39,52 @@ void main() {
expect(body1.joints.length, 0);
expect(body2.joints.length, 0);
});
+
+ test('destruction of body with joint while world is locked', () {
+ final world = World(Vector2(0.0, -10.0));
+ final bodyDef = BodyDef();
+ final body1 = world.createBody(bodyDef);
+ final body2 = world.createBody(bodyDef..position = Vector2.all(2));
+ final shape = CircleShape(radius: 1.2, position: Vector2.all(10));
+ final fixtureDef = FixtureDef(
+ shape,
+ density: 50.0,
+ friction: 0.1,
+ restitution: 0.9,
+ );
+
+ body1.createFixture(fixtureDef);
+ body2.createFixture(fixtureDef);
+
+ world.flags = World.locked;
+
+ final revoluteJointDef = RevoluteJointDef()
+ ..initialize(body1, body2, body1.position);
+ final revoluteJoint = RevoluteJoint(revoluteJointDef);
+ world.createJoint(revoluteJoint);
+
+ expect(body1.joints.length, 0);
+ expect(body2.joints.length, 0);
+
+ world.flags = 0;
+ world.stepDt(1 / 60);
+
+ expect(body1.joints.length, 1);
+ expect(body2.joints.length, 1);
+
+ world.flags = World.locked;
+
+ // Attempt to destroy the body while the world is locked
+ world.destroyBody(body1);
+ expect(body1.joints.length, 1);
+ expect(body2.joints.length, 1);
+
+ // Step the world again to process the destruction
+ world.flags = 0;
+ world.stepDt(1 / 60);
+
+ expect(body1.joints.length, 0);
+ expect(body2.joints.length, 0);
+ });
});
}