box2d_bindings.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "box2d_bindings.hpp"
  2. namespace pkpy{
  3. namespace imbox2d{
  4. void PyBody::_register(VM* vm, PyObject* mod, PyObject* type){
  5. vm->bind_notimplemented_constructor<PyBody>(type);
  6. PK_REGISTER_READONLY_PROPERTY(PyBody, debug_color, "vec4");
  7. PK_REGISTER_PROPERTY(PyBody, position, "vec2");
  8. PK_REGISTER_PROPERTY(PyBody, rotation, "float");
  9. PK_REGISTER_PROPERTY(PyBody, velocity, "vec2");
  10. PK_REGISTER_PROPERTY(PyBody, angular_velocity, "float");
  11. PK_REGISTER_PROPERTY(PyBody, damping, "float");
  12. PK_REGISTER_PROPERTY(PyBody, angular_damping, "float");
  13. PK_REGISTER_PROPERTY(PyBody, gravity_scale, "float");
  14. PK_REGISTER_PROPERTY(PyBody, type, "int");
  15. PK_REGISTER_READONLY_PROPERTY(PyBody, mass, "float");
  16. PK_REGISTER_READONLY_PROPERTY(PyBody, inertia, "float");
  17. // fixture settings
  18. PK_REGISTER_PROPERTY(PyBody, density, "float");
  19. PK_REGISTER_PROPERTY(PyBody, friction, "float");
  20. PK_REGISTER_PROPERTY(PyBody, restitution, "float");
  21. PK_REGISTER_PROPERTY(PyBody, restitution_threshold, "float");
  22. PK_REGISTER_PROPERTY(PyBody, is_trigger, "bool");
  23. // methods
  24. _bind_opaque<PyBody>(vm, type, "apply_force(self, force: vec2, point: vec2)", &Body::apply_force);
  25. _bind_opaque<PyBody>(vm, type, "apply_force_to_center(self, force: vec2)", &Body::apply_force_to_center);
  26. _bind_opaque<PyBody>(vm, type, "apply_torque(self, torque: float)", &Body::apply_torque);
  27. _bind_opaque<PyBody>(vm, type, "apply_linear_impulse(self, impulse: vec2, point: vec2)", &Body::apply_linear_impulse);
  28. _bind_opaque<PyBody>(vm, type, "apply_linear_impulse_to_center(self, impulse: vec2)", &Body::apply_linear_impulse_to_center);
  29. _bind_opaque<PyBody>(vm, type, "apply_angular_impulse(self, impulse: float)", &Body::apply_angular_impulse);
  30. vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
  31. PyBody& self = _CAST(PyBody&, lhs);
  32. if(is_non_tagged_type(rhs, PyBody::_type(vm))) return vm->NotImplemented;
  33. PyBody& other = _CAST(PyBody&, rhs);
  34. return VAR(self->body == other->body);
  35. });
  36. vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
  37. PyBody& self = _CAST(PyBody&, obj);
  38. return VAR(fmt("<Body* at ", self->body, ">"));
  39. });
  40. // destroy
  41. _bind_opaque<PyBody>(vm, type, "destroy(self)", &Body::destroy);
  42. // contacts
  43. vm->bind(type, "get_contacts(self) -> list", [](VM* vm, ArgsView args){
  44. PyBody& self = _CAST(PyBody&, args[0]);
  45. b2ContactEdge* edge = self->body->GetContactList();
  46. List list;
  47. while(edge){
  48. b2Fixture* fixtureB = edge->contact->GetFixtureB();
  49. b2Body* bodyB = fixtureB->GetBody();
  50. PyObject* objB = reinterpret_cast<Body*>(bodyB->GetUserData().pointer)->obj;
  51. list.push_back(objB);
  52. edge = edge->next;
  53. }
  54. return VAR(std::move(list));
  55. });
  56. // userdata
  57. vm->bind(type, "get_node(self)", [](VM* vm, ArgsView args){
  58. PyBody& self = _CAST(PyBody&, args[0]);
  59. return self->obj;
  60. });
  61. // shape
  62. vm->bind(type, "set_box_shape(self, hx: float, hy: float)", [](VM* vm, ArgsView args){
  63. PyBody& self = _CAST(PyBody&, args[0]);
  64. float hx = CAST(float, args[1]);
  65. float hy = CAST(float, args[2]);
  66. b2PolygonShape shape;
  67. shape.SetAsBox(hx, hy);
  68. self->_update_fixture(&shape);
  69. return vm->None;
  70. });
  71. vm->bind(type, "set_circle_shape(self, radius: float)", [](VM* vm, ArgsView args){
  72. PyBody& self = _CAST(PyBody&, args[0]);
  73. float radius = CAST(float, args[1]);
  74. b2CircleShape shape;
  75. shape.m_radius = radius;
  76. self->_update_fixture(&shape);
  77. return vm->None;
  78. });
  79. vm->bind(type, "set_polygon_shape(self, points: list[vec2])", [](VM* vm, ArgsView args){
  80. PyBody& self = _CAST(PyBody&, args[0]);
  81. List& points = CAST(List&, args[1]);
  82. if(points.size() > b2_maxPolygonVertices || points.size() < 3){
  83. vm->ValueError(fmt("invalid polygon vertices count: ", points.size()));
  84. return vm->None;
  85. }
  86. std::vector<b2Vec2> vertices(points.size());
  87. for(int i = 0; i < points.size(); ++i){
  88. vertices[i] = CAST(b2Vec2, points[i]);
  89. }
  90. b2PolygonShape shape;
  91. shape.Set(vertices.data(), vertices.size());
  92. self->_update_fixture(&shape);
  93. return vm->None;
  94. });
  95. vm->bind(type, "set_chain_shape(self, points: list[vec2])", [](VM* vm, ArgsView args){
  96. PyBody& self = _CAST(PyBody&, args[0]);
  97. List& points = CAST(List&, args[1]);
  98. std::vector<b2Vec2> vertices(points.size());
  99. for(int i = 0; i < points.size(); ++i){
  100. vertices[i] = CAST(b2Vec2, points[i]);
  101. }
  102. b2ChainShape shape;
  103. shape.CreateLoop(vertices.data(), vertices.size());
  104. self->_update_fixture(&shape);
  105. return vm->None;
  106. });
  107. vm->bind(type, "get_shape_info(self) -> tuple", [](VM* vm, ArgsView args){
  108. PyBody& self = _CAST(PyBody&, args[0]);
  109. b2Shape* shape = self->fixture->GetShape();
  110. switch(shape->GetType()){
  111. case b2Shape::e_polygon:{
  112. b2PolygonShape* poly = static_cast<b2PolygonShape*>(shape);
  113. Tuple points(poly->m_count + 1);
  114. for(int i = 0; i < poly->m_count; ++i){
  115. points[i] = VAR(poly->m_vertices[i]);
  116. }
  117. points[poly->m_count] = points[0];
  118. return VAR(Tuple({
  119. VAR("polygon"), VAR(std::move(points))
  120. }));
  121. }
  122. case b2Shape::e_circle:{
  123. b2CircleShape* circle = static_cast<b2CircleShape*>(shape);
  124. return VAR(Tuple({
  125. VAR("circle"), VAR(circle->m_radius)
  126. }));
  127. }
  128. case b2Shape::e_chain:{
  129. b2ChainShape* chain = static_cast<b2ChainShape*>(shape);
  130. Tuple points(chain->m_count);
  131. for(int i = 0; i < chain->m_count; ++i){
  132. points[i] = VAR(chain->m_vertices[i]);
  133. }
  134. return VAR(Tuple({
  135. VAR("chain"), VAR(std::move(points))
  136. }));
  137. }
  138. default:
  139. vm->ValueError("unsupported shape type");
  140. return vm->None;
  141. }
  142. });
  143. }
  144. }
  145. } // namespace pkpy