box2d_bindings.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #pragma once
  2. #include "box2d/b2_world.h"
  3. #include "box2d/box2d.h"
  4. #include "pocketpy/common.h"
  5. #include "pocketpy/pocketpy.h"
  6. namespace pkpy{
  7. template<>
  8. inline b2Vec2 py_cast<b2Vec2>(VM* vm, PyObject* obj){
  9. Vec2 v = py_cast<Vec2>(vm, obj);
  10. return b2Vec2(v.x, v.y);
  11. }
  12. template<>
  13. inline b2Vec2 _py_cast<b2Vec2>(VM* vm, PyObject* obj){
  14. Vec2 v = _py_cast<Vec2>(vm, obj);
  15. return b2Vec2(v.x, v.y);
  16. }
  17. inline PyObject* py_var(VM* vm, b2Vec2 v){
  18. return py_var(vm, Vec2(v.x, v.y));
  19. }
  20. inline PyObject* get_body_object(b2Body* p){
  21. auto userdata = p->GetUserData().pointer;
  22. return reinterpret_cast<PyObject*>(userdata);
  23. }
  24. // maybe we will use this class later
  25. struct PyDebugDraw: b2Draw{
  26. PK_ALWAYS_PASS_BY_POINTER(PyDebugDraw)
  27. VM* vm;
  28. PyObject* draw_like;
  29. PyDebugDraw(VM* vm): vm(vm){}
  30. void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override{
  31. }
  32. void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override{
  33. }
  34. void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) override{
  35. }
  36. void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) override{
  37. }
  38. void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override{
  39. }
  40. void DrawTransform(const b2Transform& xf) override{
  41. }
  42. void DrawPoint(const b2Vec2& p, float size, const b2Color& color) override{
  43. }
  44. };
  45. struct PyContactListener: b2ContactListener{
  46. PK_ALWAYS_PASS_BY_POINTER(PyContactListener)
  47. VM* vm;
  48. PyContactListener(VM* vm): vm(vm){}
  49. void _contact_f(b2Contact* contact, StrName name){
  50. b2Body* bodyA = contact->GetFixtureA()->GetBody();
  51. b2Body* bodyB = contact->GetFixtureB()->GetBody();
  52. PyObject* a = get_body_object(bodyA);
  53. PyObject* b = get_body_object(bodyB);
  54. PyObject* self;
  55. PyObject* f;
  56. f = vm->get_unbound_method(a, name, &self, false);
  57. if(f != nullptr) vm->call_method(self, f, b);
  58. f = vm->get_unbound_method(b, name, &self, false);
  59. if(f != nullptr) vm->call_method(self, f, a);
  60. }
  61. void BeginContact(b2Contact* contact) override {
  62. DEF_SNAME(on_contact_begin);
  63. _contact_f(contact, on_contact_begin);
  64. }
  65. void EndContact(b2Contact* contact) override {
  66. DEF_SNAME(on_contact_end);
  67. _contact_f(contact, on_contact_end);
  68. }
  69. };
  70. struct PyBody{
  71. PY_CLASS(PyBody, box2d, Body)
  72. PK_ALWAYS_PASS_BY_POINTER(PyBody)
  73. b2Body* body;
  74. b2Fixture* fixture;
  75. PyObject* node_like;
  76. PyBody(): body(nullptr), fixture(nullptr), node_like(nullptr){}
  77. void _gc_mark() {
  78. PK_OBJ_MARK(node_like);
  79. }
  80. PyBody& _() { return *this; }
  81. b2Body& _b2Body() { return *body; }
  82. b2Fixture& _b2Fixture() { return *fixture; }
  83. static void _register(VM* vm, PyObject* mod, PyObject* type);
  84. // methods
  85. b2Vec2 get_position() const { return body->GetPosition(); }
  86. void set_position(b2Vec2 v){ body->SetTransform(v, body->GetAngle()); }
  87. float get_rotation() const { return body->GetAngle(); }
  88. void set_rotation(float v){ body->SetTransform(body->GetPosition(), v); }
  89. void apply_force(b2Vec2 force, b2Vec2 point){ body->ApplyForce(force, point, true); }
  90. void apply_force_to_center(b2Vec2 force){ body->ApplyForceToCenter(force, true); }
  91. void apply_torque(float torque){ body->ApplyTorque(torque, true); }
  92. void apply_impulse(b2Vec2 impulse, b2Vec2 point){
  93. body->ApplyLinearImpulse(impulse, point, true);
  94. }
  95. void apply_impulse_to_center(b2Vec2 impulse){
  96. body->ApplyLinearImpulseToCenter(impulse, true);
  97. }
  98. void apply_angular_impulse(float impulse){
  99. body->ApplyAngularImpulse(impulse, true);
  100. }
  101. };
  102. struct PyWorld {
  103. PY_CLASS(PyWorld, box2d, World)
  104. PK_ALWAYS_PASS_BY_POINTER(PyWorld)
  105. b2World world;
  106. PyContactListener _contact_listener;
  107. PyDebugDraw _debug_draw;
  108. PyWorld(VM* vm);
  109. void _gc_mark(){
  110. PK_OBJ_MARK(_debug_draw.draw_like);
  111. }
  112. static void _register(VM* vm, PyObject* mod, PyObject* type);
  113. };
  114. inline void add_module_box2d(VM* vm){
  115. PyObject* mod = vm->new_module("box2d");
  116. PyBody::register_class(vm, mod);
  117. PyWorld::register_class(vm, mod);
  118. }
  119. } // namespace pkpy