diff --git a/3rd/box2d/include/box2d_bindings.hpp b/3rd/box2d/include/box2d_bindings.hpp index 4f455f8b..5b356bea 100644 --- a/3rd/box2d/include/box2d_bindings.hpp +++ b/3rd/box2d/include/box2d_bindings.hpp @@ -3,6 +3,8 @@ #include "box2d/box2d.h" #include "pocketpy/pocketpy.h" +#include + namespace pkpy{ template<> @@ -44,9 +46,17 @@ struct PyDebugDraw: b2Draw{ void DrawPoint(const b2Vec2& p, float size, const b2Color& color) override; }; +struct PyContactMessage{ + PyObject* a; + PyObject* b; + StrName name; +}; + struct PyContactListener: b2ContactListener{ PK_ALWAYS_PASS_BY_POINTER(PyContactListener) VM* vm; + std::queue messages; + PyContactListener(VM* vm): vm(vm){} void _contact_f(b2Contact* contact, StrName name); diff --git a/3rd/box2d/src/box2d_World.cpp b/3rd/box2d/src/box2d_World.cpp index 8d4ee205..4b34f665 100644 --- a/3rd/box2d/src/box2d_World.cpp +++ b/3rd/box2d/src/box2d_World.cpp @@ -32,14 +32,7 @@ struct MyBoxCastCallback: b2QueryCallback{ void PyContactListener::_contact_f(b2Contact* contact, StrName name){ PyObject* a = get_body_object(contact->GetFixtureA()->GetBody()); PyObject* b = get_body_object(contact->GetFixtureB()->GetBody()); - PyBody& bodyA = PK_OBJ_GET(PyBody, a); - PyBody& bodyB = PK_OBJ_GET(PyBody, b); - PyObject* self; - PyObject* f; - f = vm->get_unbound_method(bodyA.node_like, name, &self, false); - if(f != nullptr) vm->call_method(self, f, b); - f = vm->get_unbound_method(bodyB.node_like, name, &self, false); - if(f != nullptr) vm->call_method(self, f, a); + messages.push({a, b, name}); } /****************** PyWorld ******************/ @@ -121,6 +114,20 @@ void PyWorld::_register(VM* vm, PyObject* mod, PyObject* type){ f(vm, self.world.GetBodyList(), on_box2d_pre_step); self.world.Step(dt, velocity_iterations, position_iterations); f(vm, self.world.GetBodyList(), on_box2d_post_step); + + // clear contact messages + while(!self._contact_listener.messages.empty()){ + PyContactMessage& msg = self._contact_listener.messages.front(); + PyBody& bodyA = PK_OBJ_GET(PyBody, msg.a); + PyBody& bodyB = PK_OBJ_GET(PyBody, msg.b); + PyObject* f_self; + PyObject* f; + f = vm->get_unbound_method(bodyA.node_like, msg.name, &f_self, false); + if(f != nullptr) vm->call_method(f_self, f, msg.b); + f = vm->get_unbound_method(bodyB.node_like, msg.name, &f_self, false); + if(f != nullptr) vm->call_method(f_self, f, msg.a); + self._contact_listener.messages.pop(); + } return vm->None; });