mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
...
This commit is contained in:
parent
f16f98fcf8
commit
8eb01dc352
@ -26,6 +26,11 @@ using namespace pkpy;
|
|||||||
|
|
||||||
namespace imbox2d{
|
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
|
// maybe we will use this class later
|
||||||
struct PyDebugDraw: b2Draw{
|
struct PyDebugDraw: b2Draw{
|
||||||
PK_ALWAYS_PASS_BY_POINTER(PyDebugDraw)
|
PK_ALWAYS_PASS_BY_POINTER(PyDebugDraw)
|
||||||
@ -63,16 +68,16 @@ struct PyContactListener: b2ContactListener{
|
|||||||
PyContactListener(VM* vm): vm(vm){}
|
PyContactListener(VM* vm): vm(vm){}
|
||||||
|
|
||||||
void _contact_f(b2Contact* contact, StrName name){
|
void _contact_f(b2Contact* contact, StrName name){
|
||||||
auto a = contact->GetFixtureA()->GetBody()->GetUserData().pointer;
|
b2Body* bodyA = contact->GetFixtureA()->GetBody();
|
||||||
auto b = contact->GetFixtureB()->GetBody()->GetUserData().pointer;
|
b2Body* bodyB = contact->GetFixtureB()->GetBody();
|
||||||
Body* bodyA = reinterpret_cast<Body*>(a);
|
PyObject* a = get_body_object(bodyA);
|
||||||
Body* bodyB = reinterpret_cast<Body*>(b);
|
PyObject* b = get_body_object(bodyB);
|
||||||
PyObject* self;
|
PyObject* self;
|
||||||
PyObject* f;
|
PyObject* f;
|
||||||
f = vm->get_unbound_method(bodyA->obj, name, &self, false);
|
f = vm->get_unbound_method(a, name, &self, false);
|
||||||
if(f != nullptr) vm->call_method(self, f, VAR_T(PyBody, bodyB));
|
if(f != nullptr) vm->call_method(self, f, b);
|
||||||
f = vm->get_unbound_method(bodyB->obj, name, &self, false);
|
f = vm->get_unbound_method(b, name, &self, false);
|
||||||
if(f != nullptr) vm->call_method(self, f, VAR_T(PyBody, bodyA));
|
if(f != nullptr) vm->call_method(self, f, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BeginContact(b2Contact* contact) override {
|
void BeginContact(b2Contact* contact) override {
|
||||||
@ -100,7 +105,31 @@ struct PyBody{
|
|||||||
PK_OBJ_MARK(node_like);
|
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);
|
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 {
|
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 imbox2d
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#include "box2d/b2_world.h"
|
#include "box2d/b2_world.h"
|
||||||
#include "box2d/b2_world_callbacks.h"
|
#include "box2d/b2_world_callbacks.h"
|
||||||
#include "box2d_bindings.hpp"
|
#include "box2d_bindings.hpp"
|
||||||
|
#include "pocketpy/bindings.h"
|
||||||
|
|
||||||
using namespace pkpy;
|
using namespace pkpy;
|
||||||
|
|
||||||
namespace imbox2d{
|
namespace imbox2d{
|
||||||
|
|
||||||
|
|
||||||
void PyBody::_register(VM* vm, PyObject* mod, PyObject* type){
|
void PyBody::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind(type, "__new__(cls, world: World, node: _NodeLike = None)",
|
vm->bind(type, "__new__(cls, world: World, node: _NodeLike = None)",
|
||||||
[](VM* vm, ArgsView args){
|
[](VM* vm, ArgsView args){
|
||||||
@ -23,6 +23,66 @@ void PyBody::_register(VM* vm, PyObject* mod, PyObject* type){
|
|||||||
body.node_like = node;
|
body.node_like = node;
|
||||||
return obj;
|
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
|
} // namespace imbox2d
|
@ -48,7 +48,7 @@ void PyWorld::_register(VM* vm, PyObject* mod, PyObject* type){
|
|||||||
});
|
});
|
||||||
|
|
||||||
// gravity
|
// 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]);
|
PyWorld& self = _CAST(PyWorld&, args[0]);
|
||||||
return VAR(self.world.GetGravity());
|
return VAR(self.world.GetGravity());
|
||||||
}, [](VM* vm, ArgsView args){
|
}, [](VM* vm, ArgsView args){
|
||||||
|
@ -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
|
|
@ -90,13 +90,16 @@ class World:
|
|||||||
|
|
||||||
class Body:
|
class Body:
|
||||||
type: int # 0-static, 1-kinematic, 2-dynamic, by default 2
|
type: int # 0-static, 1-kinematic, 2-dynamic, by default 2
|
||||||
mass: float
|
|
||||||
inertia: float
|
|
||||||
gravity_scale: float
|
gravity_scale: float
|
||||||
fixed_rotation: bool
|
fixed_rotation: bool
|
||||||
enabled: bool
|
enabled: bool
|
||||||
bullet: bool # whether to use continuous collision detection
|
bullet: bool # whether to use continuous collision detection
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mass(self) -> float: ...
|
||||||
|
@property
|
||||||
|
def inertia(self) -> float: ...
|
||||||
|
|
||||||
position: vec2
|
position: vec2
|
||||||
rotation: float # in radians (counter-clockwise)
|
rotation: float # in radians (counter-clockwise)
|
||||||
velocity: vec2 # linear velocity
|
velocity: vec2 # linear velocity
|
||||||
|
Loading…
x
Reference in New Issue
Block a user