|
|
@@ -2,122 +2,47 @@
|
|
|
#include "box2d/b2_world_callbacks.h"
|
|
|
#include "box2d_bindings.hpp"
|
|
|
|
|
|
-namespace pkpy{
|
|
|
- namespace imbox2d{
|
|
|
+using namespace pkpy;
|
|
|
+
|
|
|
+namespace imbox2d{
|
|
|
+
|
|
|
+struct MyRayCastCallback: b2RayCastCallback{
|
|
|
+ PK_ALWAYS_PASS_BY_POINTER(MyRayCastCallback)
|
|
|
|
|
|
-// This class captures the closest hit shape.
|
|
|
-class MyRayCastCallback : public b2RayCastCallback
|
|
|
-{
|
|
|
VM* vm;
|
|
|
-public:
|
|
|
List result;
|
|
|
MyRayCastCallback(VM* vm): vm(vm) {}
|
|
|
|
|
|
- float ReportFixture(b2Fixture* fixture, const b2Vec2& point,
|
|
|
- const b2Vec2& normal, float fraction)
|
|
|
- {
|
|
|
- auto userdata = fixture->GetBody()->GetUserData().pointer;
|
|
|
- Body* body = reinterpret_cast<Body*>(userdata);
|
|
|
- result.push_back(VAR_T(PyBody, body));
|
|
|
+ float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float fraction){
|
|
|
+ result.push_back(get_body_object(fixture->GetBody()));
|
|
|
// if(only_one) return 0;
|
|
|
return fraction;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-class MyBoxCastCallback: public b2QueryCallback{
|
|
|
+struct MyBoxCastCallback: b2QueryCallback{
|
|
|
+ PK_ALWAYS_PASS_BY_POINTER(MyBoxCastCallback)
|
|
|
+
|
|
|
VM* vm;
|
|
|
-public:
|
|
|
List result;
|
|
|
MyBoxCastCallback(VM* vm): vm(vm) {}
|
|
|
|
|
|
bool ReportFixture(b2Fixture* fixture) override{
|
|
|
- auto userdata = fixture->GetBody()->GetUserData().pointer;
|
|
|
- Body* body = reinterpret_cast<Body*>(userdata);
|
|
|
- result.push_back(VAR_T(PyBody, body));
|
|
|
+ result.push_back(get_body_object(fixture->GetBody()));
|
|
|
return true;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-// maybe we will use this class later
|
|
|
-class PyDebugDraw: public b2Draw{
|
|
|
- VM* vm;
|
|
|
-public:
|
|
|
- PyDebugDraw(VM* vm): vm(vm){}
|
|
|
-
|
|
|
- void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override{
|
|
|
- }
|
|
|
-
|
|
|
- void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override{
|
|
|
- }
|
|
|
-
|
|
|
- void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) override{
|
|
|
- }
|
|
|
-
|
|
|
- void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) override{
|
|
|
- }
|
|
|
-
|
|
|
- void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override{
|
|
|
- }
|
|
|
-
|
|
|
- void DrawTransform(const b2Transform& xf) override{
|
|
|
- }
|
|
|
-
|
|
|
- void DrawPoint(const b2Vec2& p, float size, const b2Color& color) override{
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-class PyContactListener : public b2ContactListener{
|
|
|
- VM* vm;
|
|
|
-public:
|
|
|
- PyContactListener(VM* vm): vm(vm){}
|
|
|
-
|
|
|
- void _contact_f(b2Contact* contact, StrName name){
|
|
|
- auto a = contact->GetFixtureA()->GetBody()->GetUserData().pointer;
|
|
|
- auto b = contact->GetFixtureB()->GetBody()->GetUserData().pointer;
|
|
|
- Body* bodyA = reinterpret_cast<Body*>(a);
|
|
|
- Body* bodyB = reinterpret_cast<Body*>(b);
|
|
|
- PyObject* self;
|
|
|
- PyObject* f;
|
|
|
- f = vm->get_unbound_method(bodyA->obj, name, &self, false);
|
|
|
- if(f != nullptr) vm->call_method(self, f, VAR_T(PyBody, bodyB));
|
|
|
- f = vm->get_unbound_method(bodyB->obj, name, &self, false);
|
|
|
- if(f != nullptr) vm->call_method(self, f, VAR_T(PyBody, bodyA));
|
|
|
- }
|
|
|
-
|
|
|
- void BeginContact(b2Contact* contact) override {
|
|
|
- DEF_SNAME(on_contact_begin);
|
|
|
- _contact_f(contact, on_contact_begin);
|
|
|
- }
|
|
|
-
|
|
|
- void EndContact(b2Contact* contact) override {
|
|
|
- DEF_SNAME(on_contact_end);
|
|
|
- _contact_f(contact, on_contact_end);
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-// implement placement VAR_T...!!!!
|
|
|
-struct PyWorld {
|
|
|
- PY_CLASS(PyWorld, box2d, World)
|
|
|
-
|
|
|
- // this object is too large, so we use unique_ptr
|
|
|
- std::unique_ptr<b2World> world;
|
|
|
- std::unique_ptr<PyContactListener> _contact_listener;
|
|
|
- std::unique_ptr<PyDebugDraw> _debug_draw;
|
|
|
-
|
|
|
- PyWorld(VM* vm):
|
|
|
- world(new b2World(b2Vec2(0, 0))),
|
|
|
- _contact_listener(new PyContactListener(vm)),
|
|
|
- _debug_draw(new PyDebugDraw(vm)){
|
|
|
- world->SetAllowSleeping(true);
|
|
|
- world->SetAutoClearForces(true);
|
|
|
- world->SetContactListener(_contact_listener.get());
|
|
|
- world->SetDebugDraw(_debug_draw.get());
|
|
|
- }
|
|
|
-
|
|
|
- PyWorld(const PyWorld&) = delete;
|
|
|
- PyWorld& operator=(const PyWorld&) = delete;
|
|
|
+/****************** PyWorld ******************/
|
|
|
+PyWorld::PyWorld(VM* vm): world(b2Vec2(0, 0)), _contact_listener(vm), _debug_draw(vm){
|
|
|
+ _debug_draw.draw_like = vm->None;
|
|
|
+ world.SetAllowSleeping(true);
|
|
|
+ world.SetAutoClearForces(true);
|
|
|
+ world.SetContactListener(&_contact_listener);
|
|
|
+ world.SetDebugDraw(&_debug_draw);
|
|
|
+}
|
|
|
|
|
|
- static void _register(VM* vm, PyObject* mod, PyObject* type){
|
|
|
+void PyWorld::_register(VM* vm, PyObject* mod, PyObject* type){
|
|
|
vm->bind(type, "__new__(cls)", [](VM* vm, ArgsView args){
|
|
|
return VAR_T(PyWorld, PyWorld(vm));
|
|
|
});
|
|
|
@@ -125,20 +50,19 @@ struct PyWorld {
|
|
|
// gravity
|
|
|
vm->bind_property(type, "gravity", "vec2", [](VM* vm, ArgsView args){
|
|
|
PyWorld& self = _CAST(PyWorld&, args[0]);
|
|
|
- return VAR(self.world->GetGravity());
|
|
|
+ return VAR(self.world.GetGravity());
|
|
|
}, [](VM* vm, ArgsView args){
|
|
|
PyWorld& self = _CAST(PyWorld&, args[0]);
|
|
|
- self.world->SetGravity(CAST(b2Vec2, args[1]));
|
|
|
+ self.world.SetGravity(CAST(b2Vec2, args[1]));
|
|
|
return vm->None;
|
|
|
});
|
|
|
|
|
|
vm->bind(type, "get_bodies(self) -> list[Body]", [](VM* vm, ArgsView args){
|
|
|
PyWorld& self = _CAST(PyWorld&, args[0]);
|
|
|
List list;
|
|
|
- b2Body* p = self.world->GetBodyList();
|
|
|
+ b2Body* p = self.world.GetBodyList();
|
|
|
while(p != nullptr){
|
|
|
- Body* body = (Body*)p->GetUserData().pointer;
|
|
|
- list.push_back(VAR_T(PyBody, body));
|
|
|
+ list.push_back(get_body_object(p));
|
|
|
p = p->GetNext();
|
|
|
}
|
|
|
return VAR(std::move(list));
|
|
|
@@ -150,7 +74,7 @@ struct PyWorld {
|
|
|
b2Vec2 start = CAST(b2Vec2, args[1]);
|
|
|
b2Vec2 end = CAST(b2Vec2, args[2]);
|
|
|
MyRayCastCallback callback(vm);
|
|
|
- self.world->RayCast(&callback, start, end);
|
|
|
+ self.world.RayCast(&callback, start, end);
|
|
|
return VAR(std::move(callback.result));
|
|
|
});
|
|
|
|
|
|
@@ -161,7 +85,7 @@ struct PyWorld {
|
|
|
aabb.lowerBound = CAST(b2Vec2, args[1]);
|
|
|
aabb.upperBound = CAST(b2Vec2, args[2]);
|
|
|
MyBoxCastCallback callback(vm);
|
|
|
- self.world->QueryAABB(&callback, aabb);
|
|
|
+ self.world.QueryAABB(&callback, aabb);
|
|
|
return VAR(std::move(callback.result));
|
|
|
});
|
|
|
|
|
|
@@ -174,21 +98,36 @@ struct PyWorld {
|
|
|
|
|
|
auto f = [](VM* vm, b2Body* p, StrName name){
|
|
|
while(p != nullptr){
|
|
|
- Body* body = (Body*)p->GetUserData().pointer;
|
|
|
- vm->call_method(body->obj, name);
|
|
|
+ PyObject* body_obj = get_body_object(p);
|
|
|
+ PyBody& body = _CAST(PyBody&, body_obj);
|
|
|
+ if(body.node_like != vm->None){
|
|
|
+ vm->call_method(body.node_like, name);
|
|
|
+ }
|
|
|
p = p->GetNext();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
DEF_SNAME(on_box2d_pre_step);
|
|
|
DEF_SNAME(on_box2d_post_step);
|
|
|
- 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);
|
|
|
+ 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);
|
|
|
return vm->None;
|
|
|
});
|
|
|
- }
|
|
|
-};
|
|
|
|
|
|
- } // namespace imbox2d
|
|
|
-} // namespace pkpy
|
|
|
+ vm->bind(type, "debug_draw(self, flags: int)", [](VM* vm, ArgsView args){
|
|
|
+ PyWorld& self = _CAST(PyWorld&, args[0]);
|
|
|
+ int flags = CAST(int, args[1]);
|
|
|
+ self._debug_draw.SetFlags(flags);
|
|
|
+ self.world.DebugDraw();
|
|
|
+ return vm->None;
|
|
|
+ });
|
|
|
+
|
|
|
+ vm->bind(type, "set_debug_draw(self, draw: _DrawLike)", [](VM* vm, ArgsView args){
|
|
|
+ PyWorld& self = _CAST(PyWorld&, args[0]);
|
|
|
+ self._debug_draw.draw_like = args[1];
|
|
|
+ return vm->None;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+} // namespace imbox2d
|