mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-04 15:00:09 +01:00
Add joints test to 2D/3D physics tests
This commit is contained in:
@@ -13,9 +13,9 @@ var _drawn_nodes = []
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if (_wait_physics_ticks_counter > 0):
|
||||
if _wait_physics_ticks_counter > 0:
|
||||
_wait_physics_ticks_counter -= 1
|
||||
if (_wait_physics_ticks_counter == 0):
|
||||
if _wait_physics_ticks_counter == 0:
|
||||
emit_signal("wait_done")
|
||||
|
||||
|
||||
@@ -60,17 +60,21 @@ func clear_drawn_nodes():
|
||||
_drawn_nodes.clear()
|
||||
|
||||
|
||||
func create_rigidbody_box(size):
|
||||
var template_shape = BoxShape.new()
|
||||
template_shape.extents = 0.5 * size
|
||||
func create_rigidbody_box(size, pickable):
|
||||
var shape = BoxShape.new()
|
||||
shape.extents = 0.5 * size
|
||||
|
||||
var template_collision = CollisionShape.new()
|
||||
template_collision.shape = template_shape
|
||||
var collision = CollisionShape.new()
|
||||
collision.shape = shape
|
||||
|
||||
var template_body = RigidBody.new()
|
||||
template_body.add_child(template_collision)
|
||||
var body = RigidBody.new()
|
||||
body.add_child(collision)
|
||||
|
||||
return template_body
|
||||
if pickable:
|
||||
var script = load("res://utils/rigidbody_pick.gd")
|
||||
body.set_script(script)
|
||||
|
||||
return body
|
||||
|
||||
|
||||
func start_timer(timeout):
|
||||
|
||||
@@ -26,6 +26,10 @@ var _tests = [
|
||||
"id": "Functional Tests/Collision Pairs",
|
||||
"path": "res://tests/functional/test_collision_pairs.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Joints",
|
||||
"path": "res://tests/functional/test_joints.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Raycasting",
|
||||
"path": "res://tests/functional/test_raycasting.tscn",
|
||||
|
||||
@@ -52,16 +52,16 @@ func _ready():
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if (key_event and not key_event.pressed):
|
||||
if (key_event.scancode == KEY_1):
|
||||
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):
|
||||
elif key_event.scancode == KEY_2:
|
||||
_on_option_selected(OPTION_TYPE_SPHERE)
|
||||
elif (key_event.scancode == KEY_3):
|
||||
elif key_event.scancode == KEY_3:
|
||||
_on_option_selected(OPTION_TYPE_CAPSULE)
|
||||
elif (key_event.scancode == KEY_4):
|
||||
elif key_event.scancode == KEY_4:
|
||||
_on_option_selected(OPTION_TYPE_CYLINDER)
|
||||
elif (key_event.scancode == KEY_5):
|
||||
elif key_event.scancode == KEY_5:
|
||||
_on_option_selected(OPTION_TYPE_CONVEX_POLYGON)
|
||||
|
||||
|
||||
|
||||
139
3d/physics_tests/tests/functional/test_joints.gd
Normal file
139
3d/physics_tests/tests/functional/test_joints.gd
Normal file
@@ -0,0 +1,139 @@
|
||||
extends Test
|
||||
|
||||
|
||||
const OPTION_JOINT_TYPE = "Joint Type/%s Joint (%d)"
|
||||
|
||||
const OPTION_TEST_CASE_BODIES_COLLIDE = "Test case/Attached bodies collide"
|
||||
const OPTION_TEST_CASE_WORLD_ATTACHMENT = "Test case/No parent body"
|
||||
const OPTION_TEST_CASE_DYNAMIC_ATTACHMENT = "Test case/Parent body is dynamic (no gravity)"
|
||||
const OPTION_TEST_CASE_DESTROY_BODY = "Test case/Destroy attached body"
|
||||
const OPTION_TEST_CASE_CHANGE_POSITIONS = "Test case/Set body positions after added to scene"
|
||||
|
||||
const BOX_SIZE = Vector3(1.0, 1.0, 1.0)
|
||||
|
||||
var _update_joint = false
|
||||
var _selected_joint = null
|
||||
|
||||
var _bodies_collide = false
|
||||
var _world_attachement = false
|
||||
var _dynamic_attachement = false
|
||||
var _destroy_body = false
|
||||
var _change_positions = false
|
||||
|
||||
var _joint_types = {}
|
||||
|
||||
|
||||
func _ready():
|
||||
for joint_index in $Joints.get_child_count():
|
||||
var joint_node = $Joints.get_child(joint_index)
|
||||
joint_node.visible = false
|
||||
var joint_name = joint_node.name
|
||||
var joint_short = joint_name.substr(0, joint_name.length() - 5)
|
||||
var option_name = OPTION_JOINT_TYPE % [joint_short, joint_index + 1]
|
||||
$Options.add_menu_item(option_name)
|
||||
_joint_types[option_name] = joint_node
|
||||
|
||||
$Options.add_menu_item(OPTION_TEST_CASE_BODIES_COLLIDE, true, false)
|
||||
$Options.add_menu_item(OPTION_TEST_CASE_WORLD_ATTACHMENT, true, false)
|
||||
$Options.add_menu_item(OPTION_TEST_CASE_DYNAMIC_ATTACHMENT, true, false)
|
||||
$Options.add_menu_item(OPTION_TEST_CASE_DESTROY_BODY, true, false)
|
||||
$Options.add_menu_item(OPTION_TEST_CASE_CHANGE_POSITIONS, true, false)
|
||||
|
||||
$Options.connect("option_selected", self, "_on_option_selected")
|
||||
$Options.connect("option_changed", self, "_on_option_changed")
|
||||
|
||||
_selected_joint = _joint_types.values()[0]
|
||||
_update_joint = true
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if _update_joint:
|
||||
_update_joint = false
|
||||
_create_joint()
|
||||
$LabelJointType.text = "Joint Type: " + _selected_joint.name
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if key_event and not key_event.pressed:
|
||||
var joint_index = key_event.scancode - KEY_1
|
||||
if joint_index >= 0 and joint_index < _joint_types.size():
|
||||
_selected_joint = _joint_types.values()[joint_index]
|
||||
_update_joint = true
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
if _joint_types.has(option):
|
||||
_selected_joint = _joint_types[option]
|
||||
_update_joint = true
|
||||
|
||||
|
||||
func _on_option_changed(option, checked):
|
||||
match option:
|
||||
OPTION_TEST_CASE_BODIES_COLLIDE:
|
||||
_bodies_collide = checked
|
||||
_update_joint = true
|
||||
OPTION_TEST_CASE_WORLD_ATTACHMENT:
|
||||
_world_attachement = checked
|
||||
_update_joint = true
|
||||
OPTION_TEST_CASE_DYNAMIC_ATTACHMENT:
|
||||
_dynamic_attachement = checked
|
||||
_update_joint = true
|
||||
OPTION_TEST_CASE_DESTROY_BODY:
|
||||
_destroy_body = checked
|
||||
_update_joint = true
|
||||
OPTION_TEST_CASE_CHANGE_POSITIONS:
|
||||
_change_positions = checked
|
||||
_update_joint = true
|
||||
|
||||
|
||||
func _create_joint():
|
||||
cancel_timer()
|
||||
|
||||
var root = $Objects
|
||||
|
||||
while root.get_child_count():
|
||||
var last_child_index = root.get_child_count() - 1
|
||||
var last_child = root.get_child(last_child_index)
|
||||
root.remove_child(last_child)
|
||||
last_child.queue_free()
|
||||
|
||||
var child_body = create_rigidbody_box(BOX_SIZE, true)
|
||||
child_body.mode = RigidBody.MODE_RIGID
|
||||
if _change_positions:
|
||||
root.add_child(child_body)
|
||||
child_body.transform.origin = Vector3(0.0, -1.5, 0.0)
|
||||
else:
|
||||
child_body.transform.origin = Vector3(0.0, -1.5, 0.0)
|
||||
root.add_child(child_body)
|
||||
|
||||
var parent_body = null
|
||||
if not _world_attachement:
|
||||
parent_body = create_rigidbody_box(BOX_SIZE, true)
|
||||
if _dynamic_attachement:
|
||||
parent_body.mode = RigidBody.MODE_RIGID
|
||||
parent_body.gravity_scale = 0.0
|
||||
child_body.gravity_scale = 0.0
|
||||
else:
|
||||
parent_body.mode = RigidBody.MODE_STATIC
|
||||
if _change_positions:
|
||||
root.add_child(parent_body)
|
||||
parent_body.transform.origin = Vector3(0.0, 1.5, 0.0)
|
||||
else:
|
||||
parent_body.transform.origin = Vector3(0.0, 1.5, 0.0)
|
||||
root.add_child(parent_body)
|
||||
|
||||
var joint = _selected_joint.duplicate()
|
||||
joint.visible = true
|
||||
joint.set_exclude_nodes_from_collision(not _bodies_collide)
|
||||
if parent_body:
|
||||
joint.set_node_a(parent_body.get_path())
|
||||
joint.set_node_b(child_body.get_path())
|
||||
root.add_child(joint)
|
||||
|
||||
if _destroy_body:
|
||||
yield(start_timer(0.5), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
child_body.queue_free()
|
||||
41
3d/physics_tests/tests/functional/test_joints.tscn
Normal file
41
3d/physics_tests/tests/functional/test_joints.tscn
Normal file
@@ -0,0 +1,41 @@
|
||||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://utils/camera_orbit.gd" type="Script" id=1]
|
||||
[ext_resource path="res://tests/functional/test_joints.gd" type="Script" id=2]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=3]
|
||||
|
||||
[node name="Test" type="Spatial"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="LabelJointType" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 78.0
|
||||
margin_right = 171.0
|
||||
margin_bottom = 92.0
|
||||
text = "Joint Type: "
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 3 )]
|
||||
|
||||
[node name="Joints" type="Spatial" parent="."]
|
||||
|
||||
[node name="PinJoint" type="PinJoint" parent="Joints"]
|
||||
|
||||
[node name="HingeJoint" type="HingeJoint" parent="Joints"]
|
||||
|
||||
[node name="SliderJoint" type="SliderJoint" parent="Joints"]
|
||||
|
||||
[node name="ConeTwistJoint" type="ConeTwistJoint" parent="Joints"]
|
||||
|
||||
[node name="Generic6DOFJoint" type="Generic6DOFJoint" parent="Joints"]
|
||||
|
||||
[node name="Objects" type="Spatial" parent="."]
|
||||
|
||||
[node name="Camera" type="Camera" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 6.19796 )
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="OmniLight" type="OmniLight" parent="Camera"]
|
||||
omni_range = 50.0
|
||||
@@ -15,14 +15,7 @@ func _ready():
|
||||
func _create_pyramid():
|
||||
var root_node = $Pyramid
|
||||
|
||||
var template_shape = BoxShape.new()
|
||||
template_shape.extents = 0.5 * box_size
|
||||
|
||||
var template_collision = CollisionShape.new()
|
||||
template_collision.shape = template_shape
|
||||
|
||||
var template_body = RigidBody.new()
|
||||
template_body.add_child(template_collision)
|
||||
var template_body = create_rigidbody_box(box_size, true)
|
||||
|
||||
var pos_y = 0.5 * box_size.y + box_spacing.y
|
||||
|
||||
|
||||
@@ -15,14 +15,7 @@ func _ready():
|
||||
func _create_stack():
|
||||
var root_node = $Stack
|
||||
|
||||
var template_shape = BoxShape.new()
|
||||
template_shape.extents = 0.5 * box_size
|
||||
|
||||
var template_collision = CollisionShape.new()
|
||||
template_collision.shape = template_shape
|
||||
|
||||
var template_body = RigidBody.new()
|
||||
template_body.add_child(template_collision)
|
||||
var template_body = create_rigidbody_box(box_size, true)
|
||||
|
||||
var pos_y = 0.5 * box_size.y + box_spacing.y
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ func _ready():
|
||||
func _unhandled_input(event):
|
||||
var mouse_button_event = event as InputEventMouseButton
|
||||
if mouse_button_event:
|
||||
if mouse_button_event.button_index == BUTTON_LEFT:
|
||||
if mouse_button_event.button_index == BUTTON_RIGHT:
|
||||
_rotation_enabled = mouse_button_event.pressed
|
||||
return
|
||||
|
||||
|
||||
56
3d/physics_tests/utils/rigidbody_pick.gd
Normal file
56
3d/physics_tests/utils/rigidbody_pick.gd
Normal file
@@ -0,0 +1,56 @@
|
||||
extends RigidBody
|
||||
|
||||
|
||||
const MOUSE_DELTA_COEFFICIENT = 0.01
|
||||
const CAMERA_DISTANCE_COEFFICIENT = 0.2
|
||||
|
||||
var _picked = false
|
||||
var _last_mouse_pos = Vector2.ZERO
|
||||
var _mouse_pos = Vector2.ZERO
|
||||
|
||||
|
||||
func _ready():
|
||||
input_ray_pickable = true
|
||||
|
||||
|
||||
func _input(event):
|
||||
var mouse_event = event as InputEventMouseButton
|
||||
if mouse_event and not mouse_event.pressed:
|
||||
if mouse_event.button_index == BUTTON_LEFT:
|
||||
_picked = false
|
||||
|
||||
var mouse_motion = event as InputEventMouseMotion
|
||||
if mouse_motion:
|
||||
_mouse_pos = mouse_motion.position
|
||||
|
||||
|
||||
func _input_event(_viewport, event, _click_pos, _click_normal, _shape_idx):
|
||||
var mouse_event = event as InputEventMouseButton
|
||||
if mouse_event and mouse_event.pressed:
|
||||
if mouse_event.button_index == BUTTON_LEFT:
|
||||
_picked = true
|
||||
_mouse_pos = mouse_event.position
|
||||
_last_mouse_pos = _mouse_pos
|
||||
|
||||
|
||||
func _physics_process(delta):
|
||||
if _picked:
|
||||
var mouse_delta = _mouse_pos - _last_mouse_pos
|
||||
|
||||
var world_delta = Vector3.ZERO
|
||||
world_delta.x = mouse_delta.x * MOUSE_DELTA_COEFFICIENT
|
||||
world_delta.y = -mouse_delta.y * MOUSE_DELTA_COEFFICIENT
|
||||
|
||||
var camera = get_viewport().get_camera()
|
||||
if camera:
|
||||
var camera_basis = camera.global_transform.basis
|
||||
world_delta = camera_basis * world_delta
|
||||
|
||||
var camera_dist = camera.global_transform.origin.distance_to(global_transform.origin)
|
||||
world_delta *= CAMERA_DISTANCE_COEFFICIENT * camera_dist
|
||||
|
||||
if mode == MODE_STATIC:
|
||||
global_transform.origin += world_delta
|
||||
else:
|
||||
linear_velocity = world_delta / delta
|
||||
_last_mouse_pos = _mouse_pos
|
||||
Reference in New Issue
Block a user