test_bullet_callbacks.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import pytest
  2. from .conftest import simulate_until
  3. # Skip these tests if we can't import bullet.
  4. bullet = pytest.importorskip("panda3d.bullet")
  5. from panda3d import core
  6. bullet_filter_algorithm = core.ConfigVariableString('bullet-filter-algorithm')
  7. def test_tick(world):
  8. fired = []
  9. def callback(cd):
  10. fired.append(isinstance(cd, bullet.BulletTickCallbackData))
  11. world.set_tick_callback(callback, False)
  12. assert fired == []
  13. world.do_physics(0.1)
  14. assert fired == [True]
  15. world.clear_tick_callback()
  16. world.do_physics(0.1)
  17. assert fired == [True]
  18. @pytest.mark.skipif(bullet_filter_algorithm != 'callback', reason='bullet-filter-algorithm not set to callback')
  19. def test_filter(world, scene):
  20. # This is very similar to the basic physics test, but we're using
  21. # a filter callback to prevent collisions between the lower box and ball.
  22. # This should have the effect of the ball rolling to X>+10 without the
  23. # upper box falling at all.
  24. def callback(cd):
  25. assert isinstance(cd, bullet.BulletFilterCallbackData)
  26. if {cd.node_0.name, cd.node_1.name} == {'ball', 'lower_box'}:
  27. # ball<->lower_box collisions are excluded
  28. cd.collide = False
  29. else:
  30. # Everything else can collide
  31. cd.collide = True
  32. world.set_filter_callback(callback)
  33. ball = scene.find('**/ball')
  34. assert simulate_until(world, lambda: ball.get_x() > 10)
  35. # The upper box shouldn't fall
  36. upper_box = scene.find('**/upper_box')
  37. assert not simulate_until(world, lambda: upper_box.get_z() < 5)
  38. def test_contact(world, scene):
  39. # This just runs the basic physics test, but detects the toppling of the
  40. # upper box by a contact between upper_box<->ramp
  41. contacts = []
  42. def callback(cd):
  43. assert isinstance(cd, bullet.BulletContactCallbackData)
  44. if {cd.node0.name, cd.node1.name} == {'upper_box', 'ramp'}:
  45. if not contacts:
  46. contacts.append(True)
  47. world.set_contact_added_callback(callback)
  48. ball = scene.find('**/ball')
  49. ramp = scene.find('**/ramp')
  50. ball.node().notify_collisions(True)
  51. ramp.node().notify_collisions(True)
  52. assert simulate_until(world, lambda: ball.get_x() > 0)
  53. # Now we wait for the upper box to topple
  54. assert simulate_until(world, lambda: bool(contacts))