test_collision_pairs.gd 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. extends Test
  2. const OPTION_TYPE_BOX = "Collision type/Box (1)"
  3. const OPTION_TYPE_SPHERE = "Collision type/Sphere (2)"
  4. const OPTION_TYPE_CAPSULE = "Collision type/Capsule (3)"
  5. const OPTION_TYPE_CYLINDER = "Collision type/Cylinder (4)"
  6. const OPTION_TYPE_CONVEX_POLYGON = "Collision type/Convex Polygon (5)"
  7. const OPTION_SHAPE_BOX = "Shape type/Box"
  8. const OPTION_SHAPE_SPHERE = "Shape type/Sphere"
  9. const OPTION_SHAPE_CAPSULE = "Shape type/Capsule"
  10. const OPTION_SHAPE_CYLINDER = "Shape type/Cylinder"
  11. const OPTION_SHAPE_CONVEX_POLYGON = "Shape type/Convex Polygon"
  12. const OPTION_SHAPE_CONCAVE_POLYGON = "Shape type/Concave Polygon"
  13. const OFFSET_RANGE = 3.0
  14. @export var offset = Vector3.ZERO
  15. var _update_collision = false
  16. var _collision_test_index = 0
  17. var _current_offset = Vector3.ZERO
  18. var _collision_shapes = []
  19. func _ready():
  20. _initialize_collision_shapes()
  21. $Options.add_menu_item(OPTION_TYPE_BOX)
  22. $Options.add_menu_item(OPTION_TYPE_SPHERE)
  23. $Options.add_menu_item(OPTION_TYPE_CAPSULE)
  24. $Options.add_menu_item(OPTION_TYPE_CYLINDER)
  25. $Options.add_menu_item(OPTION_TYPE_CONVEX_POLYGON)
  26. $Options.add_menu_item(OPTION_SHAPE_BOX, true, true)
  27. $Options.add_menu_item(OPTION_SHAPE_SPHERE, true, true)
  28. $Options.add_menu_item(OPTION_SHAPE_CAPSULE, true, true)
  29. $Options.add_menu_item(OPTION_SHAPE_CYLINDER, true, true)
  30. $Options.add_menu_item(OPTION_SHAPE_CONVEX_POLYGON, true, true)
  31. $Options.add_menu_item(OPTION_SHAPE_CONCAVE_POLYGON, true, true)
  32. $Options.option_selected.connect(self._on_option_selected)
  33. $Options.option_changed.connect(self._on_option_changed)
  34. await start_timer(0.5).timeout
  35. if is_timer_canceled():
  36. return
  37. _update_collision = true
  38. func _input(event):
  39. var key_event = event as InputEventKey
  40. if key_event and not key_event.pressed:
  41. if key_event.keycode == KEY_1:
  42. _on_option_selected(OPTION_TYPE_BOX)
  43. elif key_event.keycode == KEY_2:
  44. _on_option_selected(OPTION_TYPE_SPHERE)
  45. elif key_event.keycode == KEY_3:
  46. _on_option_selected(OPTION_TYPE_CAPSULE)
  47. elif key_event.keycode == KEY_4:
  48. _on_option_selected(OPTION_TYPE_CYLINDER)
  49. elif key_event.keycode == KEY_5:
  50. _on_option_selected(OPTION_TYPE_CONVEX_POLYGON)
  51. func _physics_process(delta):
  52. super._physics_process(delta)
  53. if not _update_collision:
  54. return
  55. _update_collision = false
  56. _do_collision_test()
  57. func set_x_offset(value):
  58. offset.x = value * OFFSET_RANGE
  59. _update_collision = true
  60. func set_y_offset(value):
  61. offset.y = value * OFFSET_RANGE
  62. _update_collision = true
  63. func set_z_offset(value):
  64. offset.z = value * OFFSET_RANGE
  65. _update_collision = true
  66. func _initialize_collision_shapes():
  67. _collision_shapes.clear()
  68. for node in $Shapes.get_children():
  69. var body = node as PhysicsBody3D
  70. var shape = body.shape_owner_get_shape(0, 0)
  71. shape.resource_name = String(node.name).substr("RigidBody".length())
  72. _collision_shapes.push_back(shape)
  73. func _do_collision_test():
  74. clear_drawn_nodes()
  75. var shape = _collision_shapes[_collision_test_index]
  76. Log.print_log("* Start %s collision tests..." % shape.resource_name)
  77. var shape_query = PhysicsShapeQueryParameters3D.new()
  78. shape_query.set_shape(shape)
  79. var shape_scale = Vector3(0.5, 0.5, 0.5)
  80. shape_query.transform = Transform3D.IDENTITY.scaled(shape_scale)
  81. for node in $Shapes.get_children():
  82. if not node.visible:
  83. continue
  84. var body = node as PhysicsBody3D
  85. var space_state = body.get_world_3d().direct_space_state
  86. Log.print_log("* Testing: %s" % body.name)
  87. var center = body.global_transform.origin
  88. # Collision at the center inside.
  89. var res = _add_collision(space_state, center, shape, shape_query)
  90. Log.print_log("Collision center inside: %s" % ("NO HIT" if res.is_empty() else "HIT"))
  91. Log.print_log("* Done.")
  92. func _add_collision(space_state, pos, shape, shape_query):
  93. shape_query.transform.origin = pos + offset
  94. var results = space_state.collide_shape(shape_query)
  95. var color
  96. if results.is_empty():
  97. color = Color.WHITE.darkened(0.5)
  98. else:
  99. color = Color.GREEN
  100. # Draw collision query shape.
  101. add_shape(shape, shape_query.transform, color)
  102. # Draw contact positions.
  103. for contact_pos in results:
  104. add_sphere(contact_pos, 0.05, Color.RED)
  105. return results
  106. func _on_option_selected(option):
  107. match option:
  108. OPTION_TYPE_BOX:
  109. _collision_test_index = _find_type_index("Box")
  110. _update_collision = true
  111. OPTION_TYPE_SPHERE:
  112. _collision_test_index = _find_type_index("Sphere")
  113. _update_collision = true
  114. OPTION_TYPE_CAPSULE:
  115. _collision_test_index = _find_type_index("Capsule")
  116. _update_collision = true
  117. OPTION_TYPE_CYLINDER:
  118. _collision_test_index = _find_type_index("Cylinder")
  119. _update_collision = true
  120. OPTION_TYPE_CONVEX_POLYGON:
  121. _collision_test_index = _find_type_index("ConvexPolygon")
  122. _update_collision = true
  123. func _find_type_index(type_name):
  124. for type_index in range(_collision_shapes.size()):
  125. var type_shape = _collision_shapes[type_index]
  126. if type_shape.resource_name.find(type_name) > -1:
  127. return type_index
  128. Log.print_error("Invalid collision type: " + type_name)
  129. return -1
  130. func _on_option_changed(option, checked):
  131. var node
  132. match option:
  133. OPTION_SHAPE_BOX:
  134. node = _find_shape_node("Box")
  135. OPTION_SHAPE_SPHERE:
  136. node = _find_shape_node("Sphere")
  137. OPTION_SHAPE_CAPSULE:
  138. node = _find_shape_node("Capsule")
  139. OPTION_SHAPE_CYLINDER:
  140. node = _find_shape_node("Cylinder")
  141. OPTION_SHAPE_CONVEX_POLYGON:
  142. node = _find_shape_node("ConvexPolygon")
  143. OPTION_SHAPE_CONCAVE_POLYGON:
  144. node = _find_shape_node("ConcavePolygon")
  145. if node:
  146. node.visible = checked
  147. node.get_child(0).disabled = not checked
  148. _update_collision = true
  149. func _find_shape_node(type_name):
  150. var node = $Shapes.find_node("RigidBody%s" % type_name)
  151. if not node:
  152. Log.print_error("Invalid shape type: " + type_name)
  153. return node