box2dw.hpp 4.2 KB

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