mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-04 06:09:46 +03:00
Merge pull request #561 from nekomatata/physics-test-collision-pairs
Add collision pairs test to 2D/3D physics tests
This commit is contained in:
@@ -9,13 +9,16 @@ var _timer_started = false
|
||||
|
||||
var _wait_physics_ticks_counter = 0
|
||||
|
||||
|
||||
class Line:
|
||||
var pos_start
|
||||
var pos_end
|
||||
class Circle2D:
|
||||
extends Node2D
|
||||
var center
|
||||
var radius
|
||||
var color
|
||||
|
||||
var _lines = []
|
||||
func _draw():
|
||||
draw_circle(center, radius, color)
|
||||
|
||||
var _drawn_nodes = []
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
@@ -25,23 +28,37 @@ func _physics_process(_delta):
|
||||
emit_signal("wait_done")
|
||||
|
||||
|
||||
func _draw():
|
||||
for line in _lines:
|
||||
draw_line(line.pos_start, line.pos_end, line.color, 1.5)
|
||||
|
||||
|
||||
func add_line(pos_start, pos_end, color):
|
||||
var line = Line.new()
|
||||
line.pos_start = pos_start
|
||||
line.pos_end = pos_end
|
||||
line.color = color
|
||||
_lines.push_back(line)
|
||||
update()
|
||||
var line = Line2D.new()
|
||||
line.points = [pos_start, pos_end]
|
||||
line.width = 1.5
|
||||
line.default_color = color
|
||||
_drawn_nodes.push_back(line)
|
||||
add_child(line)
|
||||
|
||||
|
||||
func clear_lines():
|
||||
_lines.clear()
|
||||
update()
|
||||
func add_circle(pos, radius, color):
|
||||
var circle = Circle2D.new()
|
||||
circle.center = pos
|
||||
circle.radius = radius
|
||||
circle.color = color
|
||||
_drawn_nodes.push_back(circle)
|
||||
add_child(circle)
|
||||
|
||||
|
||||
func add_shape(shape, transform, color):
|
||||
var collision = CollisionShape2D.new()
|
||||
collision.shape = shape
|
||||
collision.transform = transform
|
||||
collision.modulate = color
|
||||
_drawn_nodes.push_back(collision)
|
||||
add_child(collision)
|
||||
|
||||
|
||||
func clear_drawn_nodes():
|
||||
for node in _drawn_nodes:
|
||||
node.queue_free()
|
||||
_drawn_nodes.clear()
|
||||
|
||||
|
||||
func create_rigidbody_box(size):
|
||||
|
||||
@@ -14,6 +14,10 @@ var _tests = [
|
||||
"id": "Functional Tests/Box Pyramid",
|
||||
"path": "res://tests/functional/test_pyramid.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Collision Pairs",
|
||||
"path": "res://tests/functional/test_collision_pairs.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Raycasting",
|
||||
"path": "res://tests/functional/test_raycasting.tscn",
|
||||
|
||||
206
2d/physics_tests/tests/functional/test_collision_pairs.gd
Normal file
206
2d/physics_tests/tests/functional/test_collision_pairs.gd
Normal file
@@ -0,0 +1,206 @@
|
||||
extends Test
|
||||
|
||||
|
||||
const OPTION_TYPE_RECTANGLE = "Collision type/Rectangle (1)"
|
||||
const OPTION_TYPE_SPHERE = "Collision type/Sphere (2)"
|
||||
const OPTION_TYPE_CAPSULE = "Collision type/Capsule (3)"
|
||||
const OPTION_TYPE_CONVEX_POLYGON = "Collision type/Convex Polygon (4)"
|
||||
const OPTION_TYPE_CONCAVE_SEGMENTS = "Collision type/Concave Segments (5)"
|
||||
|
||||
const OPTION_SHAPE_RECTANGLE = "Shape type/Rectangle"
|
||||
const OPTION_SHAPE_SPHERE = "Shape type/Sphere"
|
||||
const OPTION_SHAPE_CAPSULE = "Shape type/Capsule"
|
||||
const OPTION_SHAPE_CONVEX_POLYGON = "Shape type/Convex Polygon"
|
||||
const OPTION_SHAPE_CONCAVE_POLYGON = "Shape type/Concave Polygon"
|
||||
const OPTION_SHAPE_CONCAVE_SEGMENTS = "Shape type/Concave Segments"
|
||||
|
||||
const OFFSET_RANGE = 120.0
|
||||
|
||||
export(Vector2) var offset = Vector2.ZERO
|
||||
|
||||
var _update_collision = false
|
||||
var _collision_test_index = 0
|
||||
var _current_offset = Vector2.ZERO
|
||||
var _collision_shapes = []
|
||||
|
||||
|
||||
func _ready():
|
||||
_initialize_collision_shapes()
|
||||
|
||||
$Options.add_menu_item(OPTION_TYPE_RECTANGLE)
|
||||
$Options.add_menu_item(OPTION_TYPE_SPHERE)
|
||||
$Options.add_menu_item(OPTION_TYPE_CAPSULE)
|
||||
$Options.add_menu_item(OPTION_TYPE_CONVEX_POLYGON)
|
||||
$Options.add_menu_item(OPTION_TYPE_CONCAVE_SEGMENTS)
|
||||
|
||||
$Options.add_menu_item(OPTION_SHAPE_RECTANGLE, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_SPHERE, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_CAPSULE, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_CONVEX_POLYGON, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_CONCAVE_POLYGON, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_CONCAVE_SEGMENTS, true, true)
|
||||
|
||||
$Options.connect("option_selected", self, "_on_option_selected")
|
||||
$Options.connect("option_changed", self, "_on_option_changed")
|
||||
|
||||
yield(start_timer(0.5), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if (key_event and not key_event.pressed):
|
||||
if (key_event.scancode == KEY_1):
|
||||
_on_option_selected(OPTION_TYPE_RECTANGLE)
|
||||
elif (key_event.scancode == KEY_2):
|
||||
_on_option_selected(OPTION_TYPE_SPHERE)
|
||||
elif (key_event.scancode == KEY_3):
|
||||
_on_option_selected(OPTION_TYPE_CAPSULE)
|
||||
elif (key_event.scancode == KEY_4):
|
||||
_on_option_selected(OPTION_TYPE_CONVEX_POLYGON)
|
||||
elif (key_event.scancode == KEY_5):
|
||||
_on_option_selected(OPTION_TYPE_CONCAVE_SEGMENTS)
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if not _update_collision:
|
||||
return
|
||||
|
||||
_update_collision = false
|
||||
|
||||
_do_collision_test()
|
||||
|
||||
|
||||
func set_h_offset(value):
|
||||
offset.x = value * OFFSET_RANGE
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func set_v_offset(value):
|
||||
offset.y = -value * OFFSET_RANGE
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _initialize_collision_shapes():
|
||||
_collision_shapes.clear()
|
||||
|
||||
for node in $Shapes.get_children():
|
||||
var body = node as PhysicsBody2D
|
||||
var shape = body.shape_owner_get_shape(0, 0)
|
||||
shape.resource_name = node.name.substr("RigidBody".length())
|
||||
|
||||
_collision_shapes.push_back(shape)
|
||||
|
||||
|
||||
func _do_collision_test():
|
||||
clear_drawn_nodes()
|
||||
|
||||
var shape = _collision_shapes[_collision_test_index]
|
||||
|
||||
Log.print_log("* Start %s collision tests..." % shape.resource_name)
|
||||
|
||||
var shape_query = Physics2DShapeQueryParameters.new()
|
||||
shape_query.set_shape(shape)
|
||||
var shape_scale = Vector2(0.5, 0.5)
|
||||
shape_query.transform = Transform2D.IDENTITY.scaled(shape_scale)
|
||||
|
||||
for node in $Shapes.get_children():
|
||||
if not node.visible:
|
||||
continue
|
||||
|
||||
var body = node as PhysicsBody2D
|
||||
var space_state = body.get_world_2d().direct_space_state
|
||||
|
||||
Log.print_log("* Testing: %s" % body.name)
|
||||
|
||||
var center = body.position
|
||||
|
||||
# Collision at the center inside.
|
||||
var res = _add_collision(space_state, center, shape, shape_query)
|
||||
Log.print_log("Collision center inside: %s" % ("NO HIT" if res.empty() else "HIT"))
|
||||
|
||||
Log.print_log("* Done.")
|
||||
|
||||
|
||||
func _add_collision(space_state, pos, shape, shape_query):
|
||||
shape_query.transform.origin = pos + offset
|
||||
var results = space_state.collide_shape(shape_query)
|
||||
|
||||
var color
|
||||
if results.empty():
|
||||
color = Color.white.darkened(0.5)
|
||||
else:
|
||||
color = Color.green
|
||||
|
||||
# Draw collision query shape.
|
||||
add_shape(shape, shape_query.transform, color)
|
||||
|
||||
# Draw contact positions.
|
||||
for contact_pos in results:
|
||||
add_circle(contact_pos, 1.0, Color.red)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
match option:
|
||||
OPTION_TYPE_RECTANGLE:
|
||||
_collision_test_index = _find_type_index("Rectangle")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_SPHERE:
|
||||
_collision_test_index = _find_type_index("Sphere")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_CAPSULE:
|
||||
_collision_test_index = _find_type_index("Capsule")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_CONVEX_POLYGON:
|
||||
_collision_test_index = _find_type_index("ConvexPolygon")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_CONCAVE_SEGMENTS:
|
||||
_collision_test_index = _find_type_index("ConcaveSegments")
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _find_type_index(type_name):
|
||||
for type_index in _collision_shapes.size():
|
||||
var type_shape = _collision_shapes[type_index]
|
||||
if type_shape.resource_name.find(type_name) > -1:
|
||||
return type_index
|
||||
|
||||
Log.print_error("Invalid collision type: " + type_name)
|
||||
return -1
|
||||
|
||||
|
||||
func _on_option_changed(option, checked):
|
||||
var node
|
||||
|
||||
match option:
|
||||
OPTION_SHAPE_RECTANGLE:
|
||||
node = _find_shape_node("Rectangle")
|
||||
OPTION_SHAPE_SPHERE:
|
||||
node = _find_shape_node("Sphere")
|
||||
OPTION_SHAPE_CAPSULE:
|
||||
node = _find_shape_node("Capsule")
|
||||
OPTION_SHAPE_CONVEX_POLYGON:
|
||||
node = _find_shape_node("ConvexPolygon")
|
||||
OPTION_SHAPE_CONCAVE_POLYGON:
|
||||
node = _find_shape_node("ConcavePolygon")
|
||||
OPTION_SHAPE_CONCAVE_SEGMENTS:
|
||||
node = _find_shape_node("ConcaveSegments")
|
||||
|
||||
if node:
|
||||
node.visible = checked
|
||||
node.get_child(0).disabled = not checked
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _find_shape_node(type_name):
|
||||
var node = $Shapes.find_node("RigidBody%s" % type_name)
|
||||
|
||||
if not node:
|
||||
Log.print_error("Invalid shape type: " + type_name)
|
||||
|
||||
return node
|
||||
149
2d/physics_tests/tests/functional/test_collision_pairs.tscn
Normal file
149
2d/physics_tests/tests/functional/test_collision_pairs.tscn
Normal file
@@ -0,0 +1,149 @@
|
||||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_collision_pairs.gd" type="Script" id=1]
|
||||
[ext_resource path="res://assets/godot-head.png" type="Texture" id=2]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=3]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 40, 60 )
|
||||
|
||||
[sub_resource type="CircleShape2D" id=2]
|
||||
radius = 60.0
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=3]
|
||||
radius = 30.0
|
||||
height = 50.0
|
||||
|
||||
[sub_resource type="ConcavePolygonShape2D" id=4]
|
||||
segments = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 6.44476, -42.9695, 11.127, -54.3941, 11.127, -54.3941, 26.9528, -49.4309, 26.9528, -49.4309, 26.2037, -36.508, 26.2037, -36.508, 37.5346, -28.1737, 37.5346, -28.1737, 47.6282, -34.3806, 47.6282, -34.3806, 58.0427, -20.9631, 58.0427, -20.9631, 51.113, -10.2876, 51.113, -10.2876, 50.9869, 35.2694, 50.9869, 35.2694, 38.8, 47.5, 38.8, 47.5, 15.9852, 54.3613, 15.9852, 54.3613, -14.9507, 54.1845, -14.9507, 54.1845, -36.5, 48.1, -36.5, 48.1, -50.4828, 36.33, -50.4828, 36.33, -51.3668, -9.98545, -51.3668, -9.98545, -57.8889, -20.5885, -57.8889, -20.5885, -46.9473, -34.7342, -46.9473, -34.7342, -37.4014, -28.547, -37.4014, -28.547, -26.0876, -37.0323, -26.0876, -37.0323, -26.9862, -49.15, -26.9862, -49.15, -11.4152, -54.5332, -11.4152, -54.5332, -5.93512, -43.2195 )
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 3 )]
|
||||
|
||||
[node name="Shapes" type="Node2D" parent="."]
|
||||
z_index = -1
|
||||
z_as_relative = false
|
||||
|
||||
[node name="RigidBodyRectangle" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 114.877, 248.76 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyRectangle"]
|
||||
rotation = -1.19206
|
||||
scale = Vector2( 1.2, 1.2 )
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 314.894, 257.658 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodySphere"]
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="RigidBodyCapsule" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 465.629, 261.204 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyCapsule"]
|
||||
rotation = -0.202458
|
||||
scale = Vector2( 1.2, 1.2 )
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 613.385, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
polygon = PoolVector2Array( 10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, 57.9717, -20.9447, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -58.0115, -20.515, -46.9473, -34.7342, -26.0876, -50.1138, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 771.159, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
polygon = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.3941, 26.9528, -49.4309, 26.2037, -36.508, 37.5346, -28.1737, 47.6282, -34.3806, 58.0427, -20.9631, 51.113, -10.2876, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -51.3668, -9.98545, -57.8889, -20.5885, -46.9473, -34.7342, -37.4014, -28.547, -26.0876, -37.0323, -26.9862, -49.15, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="RigidBodyConcaveSegments" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 930.097, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyConcaveSegments"]
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConcaveSegments"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="Controls" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 25.3619
|
||||
margin_top = 416.765
|
||||
margin_right = 218.362
|
||||
margin_bottom = 458.765
|
||||
custom_constants/separation = 10
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="OffsetH" type="HBoxContainer" parent="Controls"]
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/OffsetH"]
|
||||
margin_top = 1.0
|
||||
margin_right = 53.0
|
||||
margin_bottom = 15.0
|
||||
text = "Offset H"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/OffsetH"]
|
||||
margin_left = 73.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 120, 0 )
|
||||
min_value = -1.0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
|
||||
[node name="OffsetV" type="HBoxContainer" parent="Controls"]
|
||||
margin_top = 26.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 42.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/OffsetV"]
|
||||
margin_left = 2.0
|
||||
margin_top = 1.0
|
||||
margin_right = 53.0
|
||||
margin_bottom = 15.0
|
||||
text = "Offset V"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/OffsetV"]
|
||||
margin_left = 73.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 120, 0 )
|
||||
min_value = -1.0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
[connection signal="value_changed" from="Controls/OffsetH/HSlider" to="." method="set_h_offset"]
|
||||
[connection signal="value_changed" from="Controls/OffsetV/HSlider" to="." method="set_v_offset"]
|
||||
@@ -13,22 +13,23 @@ func _ready():
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if !_do_raycasts:
|
||||
if not _do_raycasts:
|
||||
return
|
||||
|
||||
_do_raycasts = false
|
||||
|
||||
Log.print_log("* Start Raycasting...")
|
||||
|
||||
clear_lines()
|
||||
clear_drawn_nodes()
|
||||
|
||||
for shape in $Shapes.get_children():
|
||||
var body = shape as PhysicsBody2D
|
||||
for node in $Shapes.get_children():
|
||||
var body = node as PhysicsBody2D
|
||||
var space_state = body.get_world_2d().direct_space_state
|
||||
var body_name = body.name.substr("RigidBody".length())
|
||||
|
||||
Log.print_log("* Testing: %s" % body.name)
|
||||
Log.print_log("* Testing: %s" % body_name)
|
||||
|
||||
var center = body.global_transform.origin
|
||||
var center = body.position
|
||||
|
||||
# Raycast entering from the top.
|
||||
var res = _add_raycast(space_state, center - Vector2(0, 100), center)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=6 format=2]
|
||||
[gd_scene load_steps=7 format=2]
|
||||
|
||||
[ext_resource path="res://assets/godot-head.png" type="Texture" id=1]
|
||||
[ext_resource path="res://tests/functional/test_raycasting.gd" type="Script" id=2]
|
||||
@@ -6,12 +6,15 @@
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 40, 60 )
|
||||
|
||||
[sub_resource type="CircleShape2D" id=3]
|
||||
radius = 60.0
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=2]
|
||||
radius = 30.0
|
||||
height = 50.0
|
||||
|
||||
[sub_resource type="CircleShape2D" id=3]
|
||||
radius = 60.0
|
||||
[sub_resource type="ConcavePolygonShape2D" id=4]
|
||||
segments = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 6.44476, -42.9695, 11.127, -54.3941, 11.127, -54.3941, 26.9528, -49.4309, 26.9528, -49.4309, 26.2037, -36.508, 26.2037, -36.508, 37.5346, -28.1737, 37.5346, -28.1737, 47.6282, -34.3806, 47.6282, -34.3806, 58.0427, -20.9631, 58.0427, -20.9631, 51.113, -10.2876, 51.113, -10.2876, 50.9869, 35.2694, 50.9869, 35.2694, 38.8, 47.5, 38.8, 47.5, 15.9852, 54.3613, 15.9852, 54.3613, -14.9507, 54.1845, -14.9507, 54.1845, -36.5, 48.1, -36.5, 48.1, -50.4828, 36.33, -50.4828, 36.33, -51.3668, -9.98545, -51.3668, -9.98545, -57.8889, -20.5885, -57.8889, -20.5885, -46.9473, -34.7342, -46.9473, -34.7342, -37.4014, -28.547, -37.4014, -28.547, -26.0876, -37.0323, -26.0876, -37.0323, -26.9862, -49.15, -26.9862, -49.15, -11.4152, -54.5332, -11.4152, -54.5332, -5.93512, -43.2195 )
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 2 )
|
||||
@@ -22,47 +25,58 @@ z_as_relative = false
|
||||
|
||||
[node name="RigidBodyRectangle" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 114.877, 248.76 )
|
||||
mode = 3
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyRectangle"]
|
||||
rotation = -1.19206
|
||||
scale = Vector2( 1.5, 1.5 )
|
||||
scale = Vector2( 1.2, 1.2 )
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 314.894, 257.658 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodySphere"]
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="RigidBodyCapsule" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 313.583, 261.204 )
|
||||
mode = 3
|
||||
position = Vector2( 465.629, 261.204 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyCapsule"]
|
||||
rotation = -0.202458
|
||||
scale = Vector2( 1.5, 1.5 )
|
||||
scale = Vector2( 1.2, 1.2 )
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 514.899, 252.771 )
|
||||
mode = 3
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
polygon = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.3941, 26.9528, -49.4309, 26.2037, -36.508, 37.5346, -28.1737, 47.6282, -34.3806, 58.0427, -20.9631, 51.113, -10.2876, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -51.3668, -9.98545, -57.8889, -20.5885, -46.9473, -34.7342, -37.4014, -28.547, -26.0876, -37.0323, -26.9862, -49.15, -11.4152, -54.5332 )
|
||||
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 738.975, 252.771 )
|
||||
mode = 3
|
||||
position = Vector2( 613.385, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
polygon = PoolVector2Array( 10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, 57.9717, -20.9447, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -58.0115, -20.515, -46.9473, -34.7342, -26.0876, -50.1138, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
polygon = PoolVector2Array( 10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, 57.9717, -20.9447, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -58.0115, -20.515, -46.9473, -34.7342, -26.0876, -50.1138, -11.4152, -54.5332 )
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 771.159, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 917.136, 270.868 )
|
||||
mode = 3
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
polygon = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.3941, 26.9528, -49.4309, 26.2037, -36.508, 37.5346, -28.1737, 47.6282, -34.3806, 58.0427, -20.9631, 51.113, -10.2876, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -51.3668, -9.98545, -57.8889, -20.5885, -46.9473, -34.7342, -37.4014, -28.547, -26.0876, -37.0323, -26.9862, -49.15, -11.4152, -54.5332 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodySphere"]
|
||||
shape = SubResource( 3 )
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="RigidBodyConcaveSegments" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 930.097, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyConcaveSegments"]
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConcaveSegments"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
@@ -36,25 +36,27 @@ shape = SubResource( 2 )
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 683.614, 132.749 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
polygon = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.3941, 26.9528, -49.4309, 26.2037, -36.508, 37.5346, -28.1737, 47.6282, -34.3806, 58.0427, -20.9631, 51.113, -10.2876, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -51.3668, -9.98545, -57.8889, -20.5885, -46.9473, -34.7342, -37.4014, -28.547, -26.0876, -37.0323, -26.9862, -49.15, -11.4152, -54.5332 )
|
||||
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 473.536, 134.336 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
self_modulate = Color( 1, 1, 1, 0.392157 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 473.536, 134.336 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
polygon = PoolVector2Array( 10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, 57.9717, -20.9447, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -58.0115, -20.515, -46.9473, -34.7342, -26.0876, -50.1138, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
self_modulate = Color( 1, 1, 1, 0.392157 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 919.968, 115.129 )
|
||||
|
||||
|
||||
@@ -50,21 +50,23 @@ shape = SubResource( 3 )
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 300, 1024 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 3 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
polygon = PoolVector2Array( 10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, 57.9717, -20.9447, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -58.0115, -20.515, -46.9473, -34.7342, -26.0876, -50.1138, -11.4152, -54.5332 )
|
||||
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 400, 1024 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
self_modulate = Color( 1, 1, 1, 0.392157 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 3 )
|
||||
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 400, 1024 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
polygon = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.3941, 26.9528, -49.4309, 26.2037, -36.508, 37.5346, -28.1737, 47.6282, -34.3806, 58.0427, -20.9631, 51.113, -10.2876, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -51.3668, -9.98545, -57.8889, -20.5885, -46.9473, -34.7342, -37.4014, -28.547, -26.0876, -37.0323, -26.9862, -49.15, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
self_modulate = Color( 1, 1, 1, 0.392157 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 3 )
|
||||
|
||||
@@ -3,9 +3,10 @@ extends MenuButton
|
||||
|
||||
|
||||
signal option_selected(item_path)
|
||||
signal option_changed(item_path, checked)
|
||||
|
||||
|
||||
func add_menu_item(item_path):
|
||||
func add_menu_item(item_path, checkbox = false, checked = false):
|
||||
var path_elements = item_path.split("/", false)
|
||||
var path_element_count = path_elements.size()
|
||||
assert(path_element_count > 0)
|
||||
@@ -17,7 +18,12 @@ func add_menu_item(item_path):
|
||||
path += popup_label + "/"
|
||||
popup = _add_popup(popup, path, popup_label)
|
||||
|
||||
_add_item(popup, path_elements[path_element_count - 1])
|
||||
var label = path_elements[path_element_count - 1]
|
||||
if checkbox:
|
||||
popup.add_check_item(label)
|
||||
popup.set_item_checked(popup.get_item_count() - 1, checked)
|
||||
else:
|
||||
popup.add_item(label)
|
||||
|
||||
|
||||
func _add_item(parent_popup, label):
|
||||
@@ -33,6 +39,7 @@ func _add_popup(parent_popup, path, label):
|
||||
|
||||
var popup_menu = PopupMenu.new()
|
||||
popup_menu.name = label
|
||||
popup_menu.hide_on_checkable_item_selection = false
|
||||
|
||||
parent_popup.add_child(popup_menu)
|
||||
parent_popup.add_submenu_item(label, label)
|
||||
@@ -44,4 +51,10 @@ func _add_popup(parent_popup, path, label):
|
||||
|
||||
func _on_item_pressed(item_index, popup_menu, path):
|
||||
var item_path = path + popup_menu.get_item_text(item_index)
|
||||
emit_signal("option_selected", item_path)
|
||||
|
||||
if popup_menu.is_item_checkable(item_index):
|
||||
var checked = not popup_menu.is_item_checked(item_index)
|
||||
popup_menu.set_item_checked(item_index, checked)
|
||||
emit_signal("option_changed", item_path, checked)
|
||||
else:
|
||||
emit_signal("option_selected", item_path)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class_name Test
|
||||
extends Node
|
||||
|
||||
|
||||
signal wait_done()
|
||||
|
||||
var _timer
|
||||
@@ -8,6 +9,8 @@ var _timer_started = false
|
||||
|
||||
var _wait_physics_ticks_counter = 0
|
||||
|
||||
var _drawn_nodes = []
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if (_wait_physics_ticks_counter > 0):
|
||||
@@ -16,6 +19,47 @@ func _physics_process(_delta):
|
||||
emit_signal("wait_done")
|
||||
|
||||
|
||||
func add_sphere(pos, radius, color):
|
||||
var sphere = MeshInstance.new()
|
||||
|
||||
var sphere_mesh = SphereMesh.new()
|
||||
sphere_mesh.radius = radius
|
||||
sphere_mesh.height = radius * 2.0
|
||||
sphere.mesh = sphere_mesh
|
||||
|
||||
var material = SpatialMaterial.new()
|
||||
material.flags_unshaded = true
|
||||
material.albedo_color = color
|
||||
sphere.material_override = material
|
||||
|
||||
_drawn_nodes.push_back(sphere)
|
||||
add_child(sphere)
|
||||
|
||||
sphere.global_transform.origin = pos
|
||||
|
||||
|
||||
func add_shape(shape, transform, color):
|
||||
var collision = CollisionShape.new()
|
||||
collision.shape = shape
|
||||
|
||||
_drawn_nodes.push_back(collision)
|
||||
add_child(collision)
|
||||
|
||||
var mesh_instance = collision.get_child(0)
|
||||
var material = SpatialMaterial.new()
|
||||
material.flags_unshaded = true
|
||||
material.albedo_color = color
|
||||
mesh_instance.material_override = material
|
||||
|
||||
collision.global_transform = transform
|
||||
|
||||
|
||||
func clear_drawn_nodes():
|
||||
for node in _drawn_nodes:
|
||||
node.queue_free()
|
||||
_drawn_nodes.clear()
|
||||
|
||||
|
||||
func create_rigidbody_box(size):
|
||||
var template_shape = BoxShape.new()
|
||||
template_shape.extents = 0.5 * size
|
||||
|
||||
@@ -22,6 +22,10 @@ var _tests = [
|
||||
"id": "Functional Tests/Box Pyramid",
|
||||
"path": "res://tests/functional/test_pyramid.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Collision Pairs",
|
||||
"path": "res://tests/functional/test_collision_pairs.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Raycasting",
|
||||
"path": "res://tests/functional/test_raycasting.tscn",
|
||||
|
||||
211
3d/physics_tests/tests/functional/test_collision_pairs.gd
Normal file
211
3d/physics_tests/tests/functional/test_collision_pairs.gd
Normal file
@@ -0,0 +1,211 @@
|
||||
extends Test
|
||||
|
||||
|
||||
const OPTION_TYPE_BOX = "Collision type/Box (1)"
|
||||
const OPTION_TYPE_SPHERE = "Collision type/Sphere (2)"
|
||||
const OPTION_TYPE_CAPSULE = "Collision type/Capsule (3)"
|
||||
const OPTION_TYPE_CYLINDER = "Collision type/Cylinder (4)"
|
||||
const OPTION_TYPE_CONVEX_POLYGON = "Collision type/Convex Polygon (5)"
|
||||
|
||||
const OPTION_SHAPE_BOX = "Shape type/Box"
|
||||
const OPTION_SHAPE_SPHERE = "Shape type/Sphere"
|
||||
const OPTION_SHAPE_CAPSULE = "Shape type/Capsule"
|
||||
const OPTION_SHAPE_CYLINDER = "Shape type/Cylinder"
|
||||
const OPTION_SHAPE_CONVEX_POLYGON = "Shape type/Convex Polygon"
|
||||
const OPTION_SHAPE_CONCAVE_POLYGON = "Shape type/Concave Polygon"
|
||||
|
||||
const OFFSET_RANGE = 3.0
|
||||
|
||||
export(Vector3) var offset = Vector3.ZERO
|
||||
|
||||
var _update_collision = false
|
||||
var _collision_test_index = 0
|
||||
var _current_offset = Vector3.ZERO
|
||||
var _collision_shapes = []
|
||||
|
||||
|
||||
func _ready():
|
||||
_initialize_collision_shapes()
|
||||
|
||||
$Options.add_menu_item(OPTION_TYPE_BOX)
|
||||
$Options.add_menu_item(OPTION_TYPE_SPHERE)
|
||||
$Options.add_menu_item(OPTION_TYPE_CAPSULE)
|
||||
$Options.add_menu_item(OPTION_TYPE_CYLINDER)
|
||||
$Options.add_menu_item(OPTION_TYPE_CONVEX_POLYGON)
|
||||
|
||||
$Options.add_menu_item(OPTION_SHAPE_BOX, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_SPHERE, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_CAPSULE, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_CYLINDER, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_CONVEX_POLYGON, true, true)
|
||||
$Options.add_menu_item(OPTION_SHAPE_CONCAVE_POLYGON, true, true)
|
||||
|
||||
$Options.connect("option_selected", self, "_on_option_selected")
|
||||
$Options.connect("option_changed", self, "_on_option_changed")
|
||||
|
||||
yield(start_timer(0.5), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if (key_event and not key_event.pressed):
|
||||
if (key_event.scancode == KEY_1):
|
||||
_on_option_selected(OPTION_TYPE_BOX)
|
||||
elif (key_event.scancode == KEY_2):
|
||||
_on_option_selected(OPTION_TYPE_SPHERE)
|
||||
elif (key_event.scancode == KEY_3):
|
||||
_on_option_selected(OPTION_TYPE_CAPSULE)
|
||||
elif (key_event.scancode == KEY_4):
|
||||
_on_option_selected(OPTION_TYPE_CYLINDER)
|
||||
elif (key_event.scancode == KEY_5):
|
||||
_on_option_selected(OPTION_TYPE_CONVEX_POLYGON)
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if not _update_collision:
|
||||
return
|
||||
|
||||
_update_collision = false
|
||||
|
||||
_do_collision_test()
|
||||
|
||||
|
||||
func set_x_offset(value):
|
||||
offset.x = value * OFFSET_RANGE
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func set_y_offset(value):
|
||||
offset.y = value * OFFSET_RANGE
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func set_z_offset(value):
|
||||
offset.z = value * OFFSET_RANGE
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _initialize_collision_shapes():
|
||||
_collision_shapes.clear()
|
||||
|
||||
for node in $Shapes.get_children():
|
||||
var body = node as PhysicsBody
|
||||
var shape = body.shape_owner_get_shape(0, 0)
|
||||
shape.resource_name = node.name.substr("RigidBody".length())
|
||||
|
||||
_collision_shapes.push_back(shape)
|
||||
|
||||
|
||||
func _do_collision_test():
|
||||
clear_drawn_nodes()
|
||||
|
||||
var shape = _collision_shapes[_collision_test_index]
|
||||
|
||||
Log.print_log("* Start %s collision tests..." % shape.resource_name)
|
||||
|
||||
var shape_query = PhysicsShapeQueryParameters.new()
|
||||
shape_query.set_shape(shape)
|
||||
var shape_scale = Vector3(0.5, 0.5, 0.5)
|
||||
shape_query.transform = Transform.IDENTITY.scaled(shape_scale)
|
||||
|
||||
for node in $Shapes.get_children():
|
||||
if not node.visible:
|
||||
continue
|
||||
|
||||
var body = node as PhysicsBody
|
||||
var space_state = body.get_world().direct_space_state
|
||||
|
||||
Log.print_log("* Testing: %s" % body.name)
|
||||
|
||||
var center = body.global_transform.origin
|
||||
|
||||
# Collision at the center inside.
|
||||
var res = _add_collision(space_state, center, shape, shape_query)
|
||||
Log.print_log("Collision center inside: %s" % ("NO HIT" if res.empty() else "HIT"))
|
||||
|
||||
Log.print_log("* Done.")
|
||||
|
||||
|
||||
func _add_collision(space_state, pos, shape, shape_query):
|
||||
shape_query.transform.origin = pos + offset
|
||||
var results = space_state.collide_shape(shape_query)
|
||||
|
||||
var color
|
||||
if results.empty():
|
||||
color = Color.white.darkened(0.5)
|
||||
else:
|
||||
color = Color.green
|
||||
|
||||
# Draw collision query shape.
|
||||
add_shape(shape, shape_query.transform, color)
|
||||
|
||||
# Draw contact positions.
|
||||
for contact_pos in results:
|
||||
add_sphere(contact_pos, 0.05, Color.red)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
match option:
|
||||
OPTION_TYPE_BOX:
|
||||
_collision_test_index = _find_type_index("Box")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_SPHERE:
|
||||
_collision_test_index = _find_type_index("Sphere")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_CAPSULE:
|
||||
_collision_test_index = _find_type_index("Capsule")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_CYLINDER:
|
||||
_collision_test_index = _find_type_index("Cylinder")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_CONVEX_POLYGON:
|
||||
_collision_test_index = _find_type_index("ConvexPolygon")
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _find_type_index(type_name):
|
||||
for type_index in _collision_shapes.size():
|
||||
var type_shape = _collision_shapes[type_index]
|
||||
if type_shape.resource_name.find(type_name) > -1:
|
||||
return type_index
|
||||
|
||||
Log.print_error("Invalid collision type: " + type_name)
|
||||
return -1
|
||||
|
||||
|
||||
func _on_option_changed(option, checked):
|
||||
var node
|
||||
|
||||
match option:
|
||||
OPTION_SHAPE_BOX:
|
||||
node = _find_shape_node("Box")
|
||||
OPTION_SHAPE_SPHERE:
|
||||
node = _find_shape_node("Sphere")
|
||||
OPTION_SHAPE_CAPSULE:
|
||||
node = _find_shape_node("Capsule")
|
||||
OPTION_SHAPE_CYLINDER:
|
||||
node = _find_shape_node("Cylinder")
|
||||
OPTION_SHAPE_CONVEX_POLYGON:
|
||||
node = _find_shape_node("ConvexPolygon")
|
||||
OPTION_SHAPE_CONCAVE_POLYGON:
|
||||
node = _find_shape_node("ConcavePolygon")
|
||||
|
||||
if node:
|
||||
node.visible = checked
|
||||
node.get_child(0).disabled = not checked
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _find_shape_node(type_name):
|
||||
var node = $Shapes.find_node("RigidBody%s" % type_name)
|
||||
|
||||
if not node:
|
||||
Log.print_error("Invalid shape type: " + type_name)
|
||||
|
||||
return node
|
||||
169
3d/physics_tests/tests/functional/test_collision_pairs.tscn
Normal file
169
3d/physics_tests/tests/functional/test_collision_pairs.tscn
Normal file
@@ -0,0 +1,169 @@
|
||||
[gd_scene load_steps=11 format=2]
|
||||
|
||||
[ext_resource path="res://assets/robot_head/godot3_robot_head_collision.tres" type="Shape" id=1]
|
||||
[ext_resource path="res://tests/functional/test_collision_pairs.gd" type="Script" id=2]
|
||||
[ext_resource path="res://utils/exception_cylinder.gd" type="Script" id=3]
|
||||
[ext_resource path="res://utils/camera_orbit.gd" type="Script" id=4]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=5]
|
||||
|
||||
[sub_resource type="BoxShape" id=1]
|
||||
|
||||
[sub_resource type="SphereShape" id=5]
|
||||
|
||||
[sub_resource type="CapsuleShape" id=2]
|
||||
|
||||
[sub_resource type="CylinderShape" id=3]
|
||||
|
||||
[sub_resource type="ConvexPolygonShape" id=4]
|
||||
points = PoolVector3Array( -0.7, 0, -0.7, -0.3, 0, 0.8, 0.8, 0, -0.3, 0, -1, 0 )
|
||||
|
||||
[node name="Test" type="Spatial"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 5 )]
|
||||
|
||||
[node name="Controls" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 25.0
|
||||
margin_top = 417.0
|
||||
margin_right = -806.0
|
||||
margin_bottom = -141.0
|
||||
custom_constants/separation = 10
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="OffsetX" type="HBoxContainer" parent="Controls"]
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/OffsetX"]
|
||||
margin_left = 2.0
|
||||
margin_top = 1.0
|
||||
margin_right = 53.0
|
||||
margin_bottom = 15.0
|
||||
text = "Offset X"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/OffsetX"]
|
||||
margin_left = 73.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 120, 0 )
|
||||
min_value = -1.0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
|
||||
[node name="OffsetY" type="HBoxContainer" parent="Controls"]
|
||||
margin_top = 26.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 42.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/OffsetY"]
|
||||
margin_left = 3.0
|
||||
margin_top = 1.0
|
||||
margin_right = 53.0
|
||||
margin_bottom = 15.0
|
||||
text = "Offset Y"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/OffsetY"]
|
||||
margin_left = 73.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 120, 0 )
|
||||
min_value = -1.0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
|
||||
[node name="OffsetZ" type="HBoxContainer" parent="Controls"]
|
||||
margin_top = 52.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 68.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/OffsetZ"]
|
||||
margin_left = 2.0
|
||||
margin_top = 1.0
|
||||
margin_right = 53.0
|
||||
margin_bottom = 15.0
|
||||
text = "Offset Z"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/OffsetZ"]
|
||||
margin_left = 73.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 120, 0 )
|
||||
min_value = -1.0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
|
||||
[node name="Shapes" type="Spatial" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 9.35591, 0 )
|
||||
|
||||
[node name="RigidBodyBox" type="RigidBody" parent="Shapes"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 0, 0 )
|
||||
mode = 3
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyBox"]
|
||||
transform = Transform( 0.579556, 0.0885213, 0.145926, 0, 0.939693, -0.205212, -0.155291, 0.330366, 0.544604, 0, 0, 0 )
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody" parent="Shapes"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, 0 )
|
||||
mode = 3
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodySphere"]
|
||||
transform = Transform( 1.2, 0, 0, 0, 1.2, 0, 0, 0, 1.2, 0, 0, 0 )
|
||||
shape = SubResource( 5 )
|
||||
|
||||
[node name="RigidBodyCapsule" type="RigidBody" parent="Shapes"]
|
||||
mode = 3
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyCapsule"]
|
||||
transform = Transform( 0.8, 0, 0, 0, -1.30337e-07, -0.8, 0, 0.8, -1.30337e-07, 0, 0, 0 )
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="RigidBodyCylinder" type="RigidBody" parent="Shapes"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0 )
|
||||
mode = 3
|
||||
script = ExtResource( 3 )
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyCylinder"]
|
||||
transform = Transform( 0.772741, -0.258819, 2.59821e-08, 0.2, 0.933013, -0.207055, 0.0535898, 0.25, 0.772741, 0, 0, 0 )
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody" parent="Shapes"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 6, -0.211, 0 )
|
||||
mode = 3
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
transform = Transform( 2, 0, 0, 0, 2.89766, -0.517939, 0, 0.776908, 1.93177, 0, 0.3533, 0 )
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="RigidBodyConcavePolygon" type="StaticBody" parent="Shapes"]
|
||||
transform = Transform( 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, -6, 3.93357 )
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0 )
|
||||
shape = ExtResource( 1 )
|
||||
|
||||
[node name="Camera" type="Camera" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5.8667, 11.8164 )
|
||||
script = ExtResource( 4 )
|
||||
[connection signal="value_changed" from="Controls/OffsetX/HSlider" to="." method="set_x_offset"]
|
||||
[connection signal="value_changed" from="Controls/OffsetY/HSlider" to="." method="set_y_offset"]
|
||||
[connection signal="value_changed" from="Controls/OffsetZ/HSlider" to="." method="set_z_offset"]
|
||||
@@ -23,7 +23,7 @@ func _ready():
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if !_do_raycasts:
|
||||
if not _do_raycasts:
|
||||
return
|
||||
|
||||
_do_raycasts = false
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
[sub_resource type="BoxShape" id=1]
|
||||
|
||||
[sub_resource type="SphereShape" id=5]
|
||||
|
||||
[sub_resource type="CapsuleShape" id=2]
|
||||
|
||||
[sub_resource type="CylinderShape" id=3]
|
||||
@@ -14,8 +16,6 @@
|
||||
[sub_resource type="ConvexPolygonShape" id=4]
|
||||
points = PoolVector3Array( -0.7, 0, -0.7, -0.3, 0, 0.8, 0.8, 0, -0.3, 0, -1, 0 )
|
||||
|
||||
[sub_resource type="SphereShape" id=5]
|
||||
|
||||
[node name="Test" type="Spatial"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
@@ -30,15 +30,23 @@ mode = 3
|
||||
transform = Transform( 0.579556, 0.0885213, 0.145926, 0, 0.939693, -0.205212, -0.155291, 0.330366, 0.544604, 0, 0, 0 )
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="RigidBodyCapsule" type="RigidBody" parent="Shapes"]
|
||||
[node name="RigidBodySphere" type="RigidBody" parent="Shapes"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, 0 )
|
||||
mode = 3
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodySphere"]
|
||||
transform = Transform( 1.2, 0, 0, 0, 1.2, 0, 0, 0, 1.2, 0, 0, 0 )
|
||||
shape = SubResource( 5 )
|
||||
|
||||
[node name="RigidBodyCapsule" type="RigidBody" parent="Shapes"]
|
||||
mode = 3
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyCapsule"]
|
||||
transform = Transform( 0.8, 0, 0, 0, -1.30337e-07, -0.8, 0, 0.8, -1.30337e-07, 0, 0, 0 )
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="RigidBodyCylinder" type="RigidBody" parent="Shapes"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0 )
|
||||
mode = 3
|
||||
script = ExtResource( 3 )
|
||||
|
||||
@@ -46,22 +54,14 @@ script = ExtResource( 3 )
|
||||
transform = Transform( 0.772741, -0.258819, 2.59821e-08, 0.2, 0.933013, -0.207055, 0.0535898, 0.25, 0.772741, 0, 0, 0 )
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="RigidBodyConvex" type="RigidBody" parent="Shapes"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 3, -0.210678, 0 )
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody" parent="Shapes"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 6, -0.211, 0 )
|
||||
mode = 3
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyConvex"]
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
transform = Transform( 2, 0, 0, 0, 2.89766, -0.517939, 0, 0.776908, 1.93177, 0, 0.3533, 0 )
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody" parent="Shapes"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 0, 0 )
|
||||
mode = 3
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Shapes/RigidBodySphere"]
|
||||
transform = Transform( 1.2, 0, 0, 0, 1.2, 0, 0, 0, 1.2, 0, 0, 0 )
|
||||
shape = SubResource( 5 )
|
||||
|
||||
[node name="StaticBodyHead" type="StaticBody" parent="Shapes"]
|
||||
transform = Transform( 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, -6, 3.93357 )
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ extends Test
|
||||
|
||||
const OPTION_TYPE_ALL = "Shape type/All"
|
||||
const OPTION_TYPE_BOX = "Shape type/Box"
|
||||
const OPTION_TYPE_SPHERE = "Shape type/Sphere"
|
||||
const OPTION_TYPE_CAPSULE = "Shape type/Capsule"
|
||||
const OPTION_TYPE_CYLINDER = "Shape type/Cylinder"
|
||||
const OPTION_TYPE_CONVEX = "Shape type/Convex"
|
||||
const OPTION_TYPE_SPHERE = "Shape type/Sphere"
|
||||
export(Array) var spawns = Array()
|
||||
|
||||
export(Array) var spawns = Array()
|
||||
export(int) var spawn_count = 100
|
||||
export(int, 1, 10) var spawn_multiplier = 5
|
||||
|
||||
@@ -27,10 +27,10 @@ func _ready():
|
||||
|
||||
$Options.add_menu_item(OPTION_TYPE_ALL)
|
||||
$Options.add_menu_item(OPTION_TYPE_BOX)
|
||||
$Options.add_menu_item(OPTION_TYPE_SPHERE)
|
||||
$Options.add_menu_item(OPTION_TYPE_CAPSULE)
|
||||
$Options.add_menu_item(OPTION_TYPE_CYLINDER)
|
||||
$Options.add_menu_item(OPTION_TYPE_CONVEX)
|
||||
$Options.add_menu_item(OPTION_TYPE_SPHERE)
|
||||
$Options.connect("option_selected", self, "_on_option_selected")
|
||||
|
||||
_start_all_types()
|
||||
@@ -51,14 +51,14 @@ func _on_option_selected(option):
|
||||
_start_all_types()
|
||||
OPTION_TYPE_BOX:
|
||||
_start_type(_find_type_index("Box"))
|
||||
OPTION_TYPE_SPHERE:
|
||||
_start_type(_find_type_index("Sphere"))
|
||||
OPTION_TYPE_CAPSULE:
|
||||
_start_type(_find_type_index("Capsule"))
|
||||
OPTION_TYPE_CYLINDER:
|
||||
_start_type(_find_type_index("Cylinder"))
|
||||
OPTION_TYPE_CONVEX:
|
||||
_start_type(_find_type_index("Convex"))
|
||||
OPTION_TYPE_SPHERE:
|
||||
_start_type(_find_type_index("Sphere"))
|
||||
|
||||
|
||||
func _find_type_index(type_name):
|
||||
|
||||
@@ -3,9 +3,10 @@ extends MenuButton
|
||||
|
||||
|
||||
signal option_selected(item_path)
|
||||
signal option_changed(item_path, checked)
|
||||
|
||||
|
||||
func add_menu_item(item_path):
|
||||
func add_menu_item(item_path, checkbox = false, checked = false):
|
||||
var path_elements = item_path.split("/", false)
|
||||
var path_element_count = path_elements.size()
|
||||
assert(path_element_count > 0)
|
||||
@@ -17,7 +18,12 @@ func add_menu_item(item_path):
|
||||
path += popup_label + "/"
|
||||
popup = _add_popup(popup, path, popup_label)
|
||||
|
||||
_add_item(popup, path_elements[path_element_count - 1])
|
||||
var label = path_elements[path_element_count - 1]
|
||||
if checkbox:
|
||||
popup.add_check_item(label)
|
||||
popup.set_item_checked(popup.get_item_count() - 1, checked)
|
||||
else:
|
||||
popup.add_item(label)
|
||||
|
||||
|
||||
func _add_item(parent_popup, label):
|
||||
@@ -33,6 +39,7 @@ func _add_popup(parent_popup, path, label):
|
||||
|
||||
var popup_menu = PopupMenu.new()
|
||||
popup_menu.name = label
|
||||
popup_menu.hide_on_checkable_item_selection = false
|
||||
|
||||
parent_popup.add_child(popup_menu)
|
||||
parent_popup.add_submenu_item(label, label)
|
||||
@@ -44,4 +51,10 @@ func _add_popup(parent_popup, path, label):
|
||||
|
||||
func _on_item_pressed(item_index, popup_menu, path):
|
||||
var item_path = path + popup_menu.get_item_text(item_index)
|
||||
emit_signal("option_selected", item_path)
|
||||
|
||||
if popup_menu.is_item_checkable(item_index):
|
||||
var checked = not popup_menu.is_item_checked(item_index)
|
||||
popup_menu.set_item_checked(item_index, checked)
|
||||
emit_signal("option_changed", item_path, checked)
|
||||
else:
|
||||
emit_signal("option_selected", item_path)
|
||||
|
||||
Reference in New Issue
Block a user