blueloveTH 2 سال پیش
والد
کامیت
8eb01dc352
5فایلهای تغییر یافته به همراه104 افزوده شده و 188 حذف شده
  1. 37 14
      3rd/box2d/include/box2d_bindings.hpp
  2. 61 1
      3rd/box2d/src/box2d_Body.cpp
  3. 1 1
      3rd/box2d/src/box2d_World.cpp
  4. 0 170
      3rd/box2d/src/box2d_bindings.cpp
  5. 5 2
      docs/modules/box2d.md

+ 37 - 14
3rd/box2d/include/box2d_bindings.hpp

@@ -26,6 +26,11 @@ using namespace pkpy;
 
 namespace imbox2d{
 
+inline PyObject* get_body_object(b2Body* p){
+    auto userdata = p->GetUserData().pointer;
+    return reinterpret_cast<PyObject*>(userdata);
+}
+
 // maybe we will use this class later
 struct PyDebugDraw: b2Draw{
     PK_ALWAYS_PASS_BY_POINTER(PyDebugDraw)
@@ -63,16 +68,16 @@ struct PyContactListener: b2ContactListener{
     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);
+        b2Body* bodyA = contact->GetFixtureA()->GetBody();
+        b2Body* bodyB = contact->GetFixtureB()->GetBody();
+        PyObject* a = get_body_object(bodyA);
+        PyObject* b = get_body_object(bodyB);
         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));
+        f = vm->get_unbound_method(a, name, &self, false);
+        if(f != nullptr) vm->call_method(self, f, b);
+        f = vm->get_unbound_method(b, name, &self, false);
+        if(f != nullptr) vm->call_method(self, f, a);
     }
 
 	void BeginContact(b2Contact* contact) override {
@@ -100,7 +105,31 @@ struct PyBody{
         PK_OBJ_MARK(node_like);
     }
 
+    PyBody& _() { return *this; }
+    b2Body& _b2Body() { return *body; }
+    b2Fixture& _b2Fixture() { return *fixture; }
+
     static void _register(VM* vm, PyObject* mod, PyObject* type);
+
+    // methods
+
+    b2Vec2 get_position() const { return body->GetPosition(); }
+    void set_position(b2Vec2 v){ body->SetTransform(v, body->GetAngle()); }
+    float get_rotation() const { return body->GetAngle(); }
+    void set_rotation(float v){ body->SetTransform(body->GetPosition(), v); }
+
+    void apply_force(b2Vec2 force, b2Vec2 point){ body->ApplyForce(force, point, true); }
+    void apply_force_to_center(b2Vec2 force){ body->ApplyForceToCenter(force, true); }
+    void apply_torque(float torque){ body->ApplyTorque(torque, true); }
+    void apply_impulse(b2Vec2 impulse, b2Vec2 point){
+        body->ApplyLinearImpulse(impulse, point, true);
+    }
+    void apply_impulse_to_center(b2Vec2 impulse){
+        body->ApplyLinearImpulseToCenter(impulse, true);
+    }
+    void apply_angular_impulse(float impulse){
+        body->ApplyAngularImpulse(impulse, true);
+    }
 };
 
 struct PyWorld {
@@ -223,12 +252,6 @@ struct Body final{
     }
 };
 
-
-inline PyObject* get_body_object(b2Body* p){
-    auto userdata = p->GetUserData().pointer;
-    return reinterpret_cast<PyObject*>(userdata);
-}
-
 }   // namespace imbox2d
 
 namespace pkpy{

+ 61 - 1
3rd/box2d/src/box2d_Body.cpp

@@ -1,12 +1,12 @@
 #include "box2d/b2_world.h"
 #include "box2d/b2_world_callbacks.h"
 #include "box2d_bindings.hpp"
+#include "pocketpy/bindings.h"
 
 using namespace pkpy;
 
 namespace imbox2d{
 
-
 void PyBody::_register(VM* vm, PyObject* mod, PyObject* type){
     vm->bind(type, "__new__(cls, world: World, node: _NodeLike = None)",
         [](VM* vm, ArgsView args){
@@ -23,6 +23,66 @@ void PyBody::_register(VM* vm, PyObject* mod, PyObject* type){
             body.node_like = node;
             return obj;
         });
+
+    PK_REGISTER_PROPERTY(PyBody, "type: int", _b2Body, GetType, SetType)
+    PK_REGISTER_PROPERTY(PyBody, "gravity_scale: float", _b2Body, GetGravityScale, SetGravityScale)
+    PK_REGISTER_PROPERTY(PyBody, "fixed_rotation: bool", _b2Body, IsFixedRotation, SetFixedRotation)
+    PK_REGISTER_PROPERTY(PyBody, "enabled: bool", _b2Body, IsEnabled, SetEnabled)
+    PK_REGISTER_PROPERTY(PyBody, "bullet: bool", _b2Body, IsBullet, SetBullet)
+    
+    PK_REGISTER_READONLY_PROPERTY(PyBody, "mass: float", _b2Body, GetMass)
+    PK_REGISTER_READONLY_PROPERTY(PyBody, "inertia: float", _b2Body, GetInertia)
+
+    PK_REGISTER_PROPERTY(PyBody, "position: vec2", _, get_position, set_position)
+    PK_REGISTER_PROPERTY(PyBody, "rotation: float", _, get_rotation, set_rotation)
+    PK_REGISTER_PROPERTY(PyBody, "velocity: vec2", _b2Body, GetLinearVelocity, SetLinearVelocity)
+    PK_REGISTER_PROPERTY(PyBody, "angular_velocity: float", _b2Body, GetAngularVelocity, SetAngularVelocity)
+    PK_REGISTER_PROPERTY(PyBody, "damping: float", _b2Body, GetLinearDamping, SetLinearDamping)
+    PK_REGISTER_PROPERTY(PyBody, "angular_damping: float", _b2Body, GetAngularDamping, SetAngularDamping)
+
+    PK_REGISTER_PROPERTY(PyBody, "density: float", _b2Fixture, GetDensity, SetDensity)
+    PK_REGISTER_PROPERTY(PyBody, "friction: float", _b2Fixture, GetFriction, SetFriction)
+    PK_REGISTER_PROPERTY(PyBody, "restitution: float", _b2Fixture, GetRestitution, SetRestitution)
+    PK_REGISTER_PROPERTY(PyBody, "restitution_threshold: float", _b2Fixture, GetRestitutionThreshold, SetRestitutionThreshold)
+    PK_REGISTER_PROPERTY(PyBody, "is_trigger: bool", _b2Fixture, IsSensor, SetSensor)
+
+    // methods
+    _bind(vm, type, "apply_force(self, force: vec2, point: vec2)", &PyBody::apply_force);
+    _bind(vm, type, "apply_force_to_center(self, force: vec2)", &PyBody::apply_force_to_center);
+    _bind(vm, type, "apply_torque(self, torque: float)", &PyBody::apply_torque);
+    _bind(vm, type, "apply_impulse(self, impulse: vec2, point: vec2)", &PyBody::apply_impulse);
+    _bind(vm, type, "apply_impulse_to_center(self, impulse: vec2)", &PyBody::apply_impulse_to_center);
+    _bind(vm, type, "apply_angular_impulse(self, impulse: float)", &PyBody::apply_angular_impulse);
+
+    // get_node
+    vm->bind(type, "get_node(self)", [](VM* vm, ArgsView args){
+        PyBody& body = CAST(PyBody&, args[1]);
+        return body.node_like;
+    });
+
+    // get_contacts
+    vm->bind(type, "get_contacts(self) -> list[Body]", [](VM* vm, ArgsView args){
+        PyBody& self = _CAST(PyBody&, args[0]);
+        b2ContactEdge* edge = self.body->GetContactList();
+        List list;
+        while(edge){
+            b2Fixture* fixtureB = edge->contact->GetFixtureB();
+            b2Body* bodyB = fixtureB->GetBody();
+            list.push_back(get_body_object(bodyB));
+            edge = edge->next;
+        }
+        return VAR(std::move(list));
+    });
+
+    // destroy
+    vm->bind(type, "destroy(self)", [](VM* vm, ArgsView args){
+        PyBody& body = CAST(PyBody&, args[1]);
+        body.body->GetWorld()->DestroyBody(body.body);
+        body.body = nullptr;
+        body.fixture = nullptr;
+        body.node_like = nullptr;
+        return vm->None;
+    });
 }
 
 }   // namespace imbox2d

+ 1 - 1
3rd/box2d/src/box2d_World.cpp

@@ -48,7 +48,7 @@ void PyWorld::_register(VM* vm, PyObject* mod, PyObject* type){
     });
 
     // gravity
-    vm->bind_property(type, "gravity", "vec2", [](VM* vm, ArgsView args){
+    vm->bind_property(type, "gravity: vec2", [](VM* vm, ArgsView args){
         PyWorld& self = _CAST(PyWorld&, args[0]);
         return VAR(self.world.GetGravity());
     }, [](VM* vm, ArgsView args){

+ 0 - 170
3rd/box2d/src/box2d_bindings.cpp

@@ -1,170 +0,0 @@
-#include "box2d_bindings.hpp"
-
-namespace pkpy{
-
-namespace imbox2d{
-
-
-
-    void PyBody::_register(VM* vm, PyObject* mod, PyObject* type){
-        vm->bind_notimplemented_constructor<PyBody>(type);
-        PK_REGISTER_READONLY_PROPERTY(PyBody, debug_color, "vec4");
-
-        PK_REGISTER_PROPERTY(PyBody, position, "vec2");
-        PK_REGISTER_PROPERTY(PyBody, rotation, "float");
-        PK_REGISTER_PROPERTY(PyBody, velocity, "vec2");
-        PK_REGISTER_PROPERTY(PyBody, angular_velocity, "float");
-        PK_REGISTER_PROPERTY(PyBody, damping, "float");
-        PK_REGISTER_PROPERTY(PyBody, angular_damping, "float");
-        PK_REGISTER_PROPERTY(PyBody, gravity_scale, "float");
-        PK_REGISTER_PROPERTY(PyBody, type, "int");
-        PK_REGISTER_READONLY_PROPERTY(PyBody, mass, "float");
-        PK_REGISTER_READONLY_PROPERTY(PyBody, inertia, "float");
-
-        // fixture settings
-        PK_REGISTER_PROPERTY(PyBody, density, "float");
-        PK_REGISTER_PROPERTY(PyBody, friction, "float");
-        PK_REGISTER_PROPERTY(PyBody, restitution, "float");
-        PK_REGISTER_PROPERTY(PyBody, restitution_threshold, "float");
-        PK_REGISTER_PROPERTY(PyBody, is_trigger, "bool");
-
-        // methods
-        _bind_opaque<PyBody>(vm, type, "apply_force(self, force: vec2, point: vec2)", &Body::apply_force);
-        _bind_opaque<PyBody>(vm, type, "apply_force_to_center(self, force: vec2)", &Body::apply_force_to_center);
-        _bind_opaque<PyBody>(vm, type, "apply_torque(self, torque: float)", &Body::apply_torque);
-        _bind_opaque<PyBody>(vm, type, "apply_linear_impulse(self, impulse: vec2, point: vec2)", &Body::apply_linear_impulse);
-        _bind_opaque<PyBody>(vm, type, "apply_linear_impulse_to_center(self, impulse: vec2)", &Body::apply_linear_impulse_to_center);
-        _bind_opaque<PyBody>(vm, type, "apply_angular_impulse(self, impulse: float)", &Body::apply_angular_impulse);
-
-        vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
-            PyBody& self = _CAST(PyBody&, lhs);
-            if(is_non_tagged_type(rhs, PyBody::_type(vm))) return vm->NotImplemented;
-            PyBody& other = _CAST(PyBody&, rhs);
-            return VAR(self->body == other->body);
-        });
-
-        vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
-            PyBody& self = _CAST(PyBody&, obj);
-            return VAR(fmt("<Body* at ", self->body, ">"));
-        });
-
-        // destroy
-        _bind_opaque<PyBody>(vm, type, "destroy(self)", &Body::destroy);
-
-        // contacts
-        vm->bind(type, "get_contacts(self) -> list", [](VM* vm, ArgsView args){
-            PyBody& self = _CAST(PyBody&, args[0]);
-            b2ContactEdge* edge = self->body->GetContactList();
-            List list;
-            while(edge){
-                b2Fixture* fixtureB = edge->contact->GetFixtureB();
-                b2Body* bodyB = fixtureB->GetBody();
-                PyObject* objB = reinterpret_cast<Body*>(bodyB->GetUserData().pointer)->obj;
-                list.push_back(objB);
-                edge = edge->next;
-            }
-            return VAR(std::move(list));
-        });
-
-        // userdata
-        vm->bind(type, "get_node(self)", [](VM* vm, ArgsView args){
-            PyBody& self = _CAST(PyBody&, args[0]);
-            return self->obj;
-        });
-
-        // shape
-        vm->bind(type, "set_box_shape(self, hx: float, hy: float)", [](VM* vm, ArgsView args){
-            PyBody& self = _CAST(PyBody&, args[0]);
-            float hx = CAST(float, args[1]);
-            float hy = CAST(float, args[2]);
-            b2PolygonShape shape;
-            shape.SetAsBox(hx, hy);
-            self->_update_fixture(&shape);
-            return vm->None;
-        });
-
-        vm->bind(type, "set_circle_shape(self, radius: float)", [](VM* vm, ArgsView args){
-            PyBody& self = _CAST(PyBody&, args[0]);
-            float radius = CAST(float, args[1]);
-            b2CircleShape shape;
-            shape.m_radius = radius;
-            self->_update_fixture(&shape);
-            return vm->None;
-        });
-
-        vm->bind(type, "set_polygon_shape(self, points: list[vec2])", [](VM* vm, ArgsView args){
-            PyBody& self = _CAST(PyBody&, args[0]);
-            List& points = CAST(List&, args[1]);
-            if(points.size() > b2_maxPolygonVertices || points.size() < 3){
-                vm->ValueError(fmt("invalid polygon vertices count: ", points.size()));
-                return vm->None;
-            }
-            std::vector<b2Vec2> vertices(points.size());
-            for(int i = 0; i < points.size(); ++i){
-                vertices[i] = CAST(b2Vec2, points[i]);
-            }
-            b2PolygonShape shape;
-            shape.Set(vertices.data(), vertices.size());
-            self->_update_fixture(&shape);
-            return vm->None;
-        });
-
-        vm->bind(type, "set_chain_shape(self, points: list[vec2])", [](VM* vm, ArgsView args){
-            PyBody& self = _CAST(PyBody&, args[0]);
-            List& points = CAST(List&, args[1]);
-            std::vector<b2Vec2> vertices(points.size());
-            for(int i = 0; i < points.size(); ++i){
-                vertices[i] = CAST(b2Vec2, points[i]);
-            }
-            b2ChainShape shape;
-            shape.CreateLoop(vertices.data(), vertices.size());
-            self->_update_fixture(&shape);
-            return vm->None;
-        });
-
-        vm->bind(type, "get_shape_info(self) -> tuple", [](VM* vm, ArgsView args){
-            PyBody& self = _CAST(PyBody&, args[0]);
-            b2Shape* shape = self->fixture->GetShape();
-            switch(shape->GetType()){
-                case b2Shape::e_polygon:{
-                    b2PolygonShape* poly = static_cast<b2PolygonShape*>(shape);
-                    Tuple points(poly->m_count + 1);
-                    for(int i = 0; i < poly->m_count; ++i){
-                        points[i] = VAR(poly->m_vertices[i]);
-                    }
-                    points[poly->m_count] = points[0];
-                    return VAR(Tuple({
-                        VAR("polygon"), VAR(std::move(points))
-                    }));
-                }
-                case b2Shape::e_circle:{
-                    b2CircleShape* circle = static_cast<b2CircleShape*>(shape);
-                    return VAR(Tuple({
-                        VAR("circle"), VAR(circle->m_radius)
-                    }));
-                }
-                case b2Shape::e_chain:{
-                    b2ChainShape* chain = static_cast<b2ChainShape*>(shape);
-                    Tuple points(chain->m_count);
-                    for(int i = 0; i < chain->m_count; ++i){
-                        points[i] = VAR(chain->m_vertices[i]);
-                    }
-                    return VAR(Tuple({
-                        VAR("chain"), VAR(std::move(points))
-                    }));
-                }
-                default:
-                    vm->ValueError("unsupported shape type");
-                    return vm->None;
-            }
-        });
-    }
-
-
-
-
-
-
-}
-
-}   // namespace pkpy

+ 5 - 2
docs/modules/box2d.md

@@ -90,13 +90,16 @@ class World:
 
 class Body:
     type: int           # 0-static, 1-kinematic, 2-dynamic, by default 2
-    mass: float
-    inertia: float
     gravity_scale: float
     fixed_rotation: bool
     enabled: bool
     bullet: bool        # whether to use continuous collision detection
 
+    @property
+    def mass(self) -> float: ...
+    @property
+    def inertia(self) -> float: ...
+
     position: vec2
     rotation: float     # in radians (counter-clockwise)
     velocity: vec2      # linear velocity