mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-04 06:09:46 +03:00
Add One Way Collision for 2D Physics tests
This commit is contained in:
@@ -18,6 +18,10 @@ var _tests = [
|
||||
"id": "Functional Tests/Collision Pairs",
|
||||
"path": "res://tests/functional/test_collision_pairs.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/One Way Collision",
|
||||
"path": "res://tests/functional/test_one_way_collision.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Joints",
|
||||
"path": "res://tests/functional/test_joints.tscn",
|
||||
|
||||
277
2d/physics_tests/tests/functional/test_one_way_collision.gd
Normal file
277
2d/physics_tests/tests/functional/test_one_way_collision.gd
Normal file
@@ -0,0 +1,277 @@
|
||||
extends Test
|
||||
tool
|
||||
|
||||
const OPTION_OBJECT_TYPE_RIGIDBODY = "Object type/Rigid body (1)"
|
||||
const OPTION_OBJECT_TYPE_KINEMATIC = "Object type/Kinematic body (2)"
|
||||
|
||||
const OPTION_TEST_CASE_ALL_ANGLES = "Test case/Around the clock (0)"
|
||||
|
||||
const TEST_ALL_ANGLES_STEP = 15.0
|
||||
const TEST_ALL_ANGLES_MAX = 344.0
|
||||
|
||||
export(float, 32, 128, 0.1) var _platform_size = 64.0 setget _set_platform_size
|
||||
export(float, 0, 360, 0.1) var _platform_angle = 0.0 setget _set_platform_angle
|
||||
export(float, 0, 360, 0.1) var _body_angle = 0.0 setget _set_rigidbody_angle
|
||||
export(Vector2) var _body_velocity = Vector2(400.0, 0.0)
|
||||
export(bool) var _use_kinematic_body = false
|
||||
|
||||
var _rigid_body_template = null
|
||||
var _kinematic_body_template = null
|
||||
var _moving_body = null
|
||||
|
||||
var _contact_detected = false
|
||||
var _target_entered = false
|
||||
var _test_passed = false
|
||||
var _test_step = 0
|
||||
|
||||
var _test_all_angles = false
|
||||
var _lock_controls = false
|
||||
|
||||
|
||||
func _ready():
|
||||
if not Engine.editor_hint:
|
||||
$Options.add_menu_item(OPTION_OBJECT_TYPE_RIGIDBODY, true, not _use_kinematic_body, true)
|
||||
$Options.add_menu_item(OPTION_OBJECT_TYPE_KINEMATIC, true, _use_kinematic_body, true)
|
||||
|
||||
$Options.add_menu_item(OPTION_TEST_CASE_ALL_ANGLES)
|
||||
|
||||
$Options.connect("option_selected", self, "_on_option_selected")
|
||||
|
||||
$Controls/PlatformSize/HSlider.value = _platform_size
|
||||
$Controls/PlatformAngle/HSlider.value = _platform_angle
|
||||
$Controls/BodyAngle/HSlider.value = _body_angle
|
||||
|
||||
$TargetArea2D.connect("body_entered", self, "_on_target_entered")
|
||||
$Timer.connect("timeout", self, "_on_timeout")
|
||||
|
||||
_rigid_body_template = $RigidBody2D
|
||||
remove_child(_rigid_body_template)
|
||||
|
||||
_kinematic_body_template = $KinematicBody2D
|
||||
remove_child(_kinematic_body_template)
|
||||
|
||||
_start_test()
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if not Engine.editor_hint:
|
||||
if Input.is_action_just_pressed("ui_accept"):
|
||||
_reset_test(false)
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if not Engine.editor_hint:
|
||||
if _moving_body and _use_kinematic_body:
|
||||
_moving_body.move_and_slide(_body_velocity)
|
||||
if _moving_body.get_slide_count() > 0:
|
||||
var colliding_body = _moving_body.get_slide_collision(0).collider
|
||||
_on_contact_detected(colliding_body)
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if key_event and not key_event.pressed:
|
||||
if key_event.scancode == KEY_0:
|
||||
_on_option_selected(OPTION_TEST_CASE_ALL_ANGLES)
|
||||
if key_event.scancode == KEY_1:
|
||||
_on_option_selected(OPTION_OBJECT_TYPE_RIGIDBODY)
|
||||
elif key_event.scancode == KEY_2:
|
||||
_on_option_selected(OPTION_OBJECT_TYPE_KINEMATIC)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
if not Engine.editor_hint:
|
||||
_rigid_body_template.free()
|
||||
_kinematic_body_template.free()
|
||||
|
||||
|
||||
func _set_platform_size(value):
|
||||
if _lock_controls:
|
||||
return
|
||||
if value == _platform_size:
|
||||
return
|
||||
_platform_size = value
|
||||
if is_inside_tree():
|
||||
$OneWayRigidBody2D/CollisionShape2D.shape.extents.x = value
|
||||
|
||||
if not Engine.editor_hint:
|
||||
# Bug: need to re-add when changing shape.
|
||||
var platform = $OneWayRigidBody2D
|
||||
var child_index = platform.get_index()
|
||||
remove_child(platform)
|
||||
add_child(platform)
|
||||
move_child(platform, child_index)
|
||||
|
||||
_reset_test()
|
||||
|
||||
|
||||
func _set_platform_angle(value):
|
||||
if _lock_controls:
|
||||
return
|
||||
if value == _platform_angle:
|
||||
return
|
||||
_platform_angle = value
|
||||
if is_inside_tree():
|
||||
$OneWayRigidBody2D.rotation = deg2rad(value)
|
||||
if not Engine.editor_hint:
|
||||
_reset_test()
|
||||
|
||||
|
||||
func _set_rigidbody_angle(value):
|
||||
if _lock_controls:
|
||||
return
|
||||
if value == _body_angle:
|
||||
return
|
||||
_body_angle = value
|
||||
if is_inside_tree():
|
||||
if Engine.editor_hint:
|
||||
$RigidBody2D.rotation = deg2rad(value)
|
||||
$KinematicBody2D.rotation = deg2rad(value)
|
||||
else:
|
||||
if _moving_body:
|
||||
_moving_body.rotation = deg2rad(value)
|
||||
_rigid_body_template.rotation = deg2rad(value)
|
||||
_kinematic_body_template.rotation = deg2rad(value)
|
||||
_reset_test()
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
match option:
|
||||
OPTION_OBJECT_TYPE_KINEMATIC:
|
||||
_use_kinematic_body = true
|
||||
_reset_test()
|
||||
OPTION_OBJECT_TYPE_RIGIDBODY:
|
||||
_use_kinematic_body = false
|
||||
_reset_test()
|
||||
OPTION_TEST_CASE_ALL_ANGLES:
|
||||
_test_all_angles = true
|
||||
_reset_test(false)
|
||||
|
||||
|
||||
func _start_test():
|
||||
var test_label = "Testing: "
|
||||
|
||||
if _use_kinematic_body:
|
||||
test_label += _kinematic_body_template.name
|
||||
_moving_body = _kinematic_body_template.duplicate()
|
||||
else:
|
||||
test_label += _rigid_body_template.name
|
||||
_moving_body = _rigid_body_template.duplicate()
|
||||
_moving_body.linear_velocity = _body_velocity
|
||||
_moving_body.connect("body_entered", self, "_on_contact_detected")
|
||||
add_child(_moving_body)
|
||||
|
||||
if _test_all_angles:
|
||||
test_label += " - All angles"
|
||||
|
||||
$LabelTestType.text = test_label
|
||||
|
||||
_contact_detected = false
|
||||
_target_entered = false
|
||||
_test_passed = false
|
||||
_test_step += 1
|
||||
|
||||
$Timer.start()
|
||||
|
||||
$LabelResult.text = "..."
|
||||
$LabelResult.self_modulate = Color.white
|
||||
|
||||
|
||||
func _reset_test(cancel_test = true):
|
||||
$Timer.stop()
|
||||
|
||||
_test_step = 0
|
||||
|
||||
if _test_all_angles:
|
||||
if cancel_test:
|
||||
Log.print_log("*** Stop around the clock tests")
|
||||
_test_all_angles = false
|
||||
else:
|
||||
Log.print_log("*** Start around the clock tests")
|
||||
$OneWayRigidBody2D.rotation = deg2rad(_platform_angle)
|
||||
_lock_controls = true
|
||||
$Controls/PlatformAngle/HSlider.value = _platform_angle
|
||||
_lock_controls = false
|
||||
|
||||
_next_test(true)
|
||||
|
||||
|
||||
func _next_test(force_start = false):
|
||||
if _moving_body:
|
||||
remove_child(_moving_body)
|
||||
_moving_body.queue_free()
|
||||
_moving_body = null
|
||||
|
||||
if _test_all_angles:
|
||||
var angle = rad2deg($OneWayRigidBody2D.rotation)
|
||||
if angle >= _platform_angle + TEST_ALL_ANGLES_MAX:
|
||||
$OneWayRigidBody2D.rotation = deg2rad(_platform_angle)
|
||||
_lock_controls = true
|
||||
$Controls/PlatformAngle/HSlider.value = _platform_angle
|
||||
_lock_controls = false
|
||||
Log.print_log("*** Done all angles")
|
||||
else:
|
||||
angle = _platform_angle + _test_step * TEST_ALL_ANGLES_STEP
|
||||
$OneWayRigidBody2D.rotation = deg2rad(angle)
|
||||
_lock_controls = true
|
||||
$Controls/PlatformAngle/HSlider.value = angle
|
||||
_lock_controls = false
|
||||
_start_test()
|
||||
elif force_start:
|
||||
_start_test()
|
||||
|
||||
|
||||
func _on_contact_detected(_body):
|
||||
if _contact_detected or _target_entered:
|
||||
return
|
||||
|
||||
_contact_detected = true
|
||||
_test_passed = _should_collide()
|
||||
_set_result()
|
||||
_on_timeout()
|
||||
|
||||
|
||||
func _on_target_entered(_body):
|
||||
if _contact_detected or _target_entered:
|
||||
return
|
||||
|
||||
_target_entered = true
|
||||
_test_passed = not _should_collide()
|
||||
_set_result()
|
||||
_on_timeout()
|
||||
|
||||
|
||||
func _should_collide():
|
||||
var platform_rotation = round(rad2deg($OneWayRigidBody2D.rotation))
|
||||
|
||||
var angle = fposmod(platform_rotation, 360)
|
||||
return angle > 180
|
||||
|
||||
|
||||
func _on_timeout():
|
||||
if not _contact_detected and not _target_entered:
|
||||
Log.print_log("Test TIMEOUT")
|
||||
_set_result()
|
||||
|
||||
$Timer.stop()
|
||||
|
||||
yield(get_tree().create_timer(0.5), "timeout")
|
||||
|
||||
_next_test()
|
||||
|
||||
|
||||
func _set_result():
|
||||
var result = ""
|
||||
if _test_passed:
|
||||
result = "PASSED"
|
||||
$LabelResult.self_modulate = Color.green
|
||||
else:
|
||||
result = "FAILED"
|
||||
$LabelResult.self_modulate = Color.red
|
||||
|
||||
$LabelResult.text = result
|
||||
|
||||
var platform_angle = rad2deg($OneWayRigidBody2D.rotation)
|
||||
|
||||
result += ": size=%.1f, angle=%.1f, body angle=%.1f" % [_platform_size, platform_angle, _body_angle]
|
||||
Log.print_log("Test %s" % result)
|
||||
243
2d/physics_tests/tests/functional/test_one_way_collision.tscn
Normal file
243
2d/physics_tests/tests/functional/test_one_way_collision.tscn
Normal file
@@ -0,0 +1,243 @@
|
||||
[gd_scene load_steps=9 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_one_way_collision.gd" type="Script" id=1]
|
||||
[ext_resource path="res://icon.png" type="Texture" id=2]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://utils/label_slider_value.gd" type="Script" id=4]
|
||||
[ext_resource path="res://utils/slider.gd" type="Script" id=5]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 32, 32 )
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=2]
|
||||
extents = Vector2( 64, 32 )
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=3]
|
||||
extents = Vector2( 32, 32 )
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="LabelTestType" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 79.0
|
||||
margin_right = 145.0
|
||||
margin_bottom = 93.0
|
||||
text = "Testing: "
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 3 )]
|
||||
|
||||
[node name="Controls" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 25.3619
|
||||
margin_top = 416.765
|
||||
margin_right = 265.362
|
||||
margin_bottom = 484.765
|
||||
custom_constants/separation = 10
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PlatformSize" type="HBoxContainer" parent="Controls"]
|
||||
margin_right = 432.0
|
||||
margin_bottom = 16.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/PlatformSize"]
|
||||
margin_left = 8.0
|
||||
margin_top = 1.0
|
||||
margin_right = 92.0
|
||||
margin_bottom = 15.0
|
||||
text = "Platform size"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/PlatformSize"]
|
||||
margin_left = 112.0
|
||||
margin_right = 312.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 200, 0 )
|
||||
min_value = 32.0
|
||||
max_value = 128.0
|
||||
value = 64.0
|
||||
script = ExtResource( 5 )
|
||||
|
||||
[node name="LabelValue" type="Label" parent="Controls/PlatformSize"]
|
||||
margin_left = 332.0
|
||||
margin_top = 1.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 15.0
|
||||
rect_min_size = Vector2( 100, 0 )
|
||||
text = "64.0"
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="PlatformAngle" type="HBoxContainer" parent="Controls"]
|
||||
margin_top = 26.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 42.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/PlatformAngle"]
|
||||
margin_top = 1.0
|
||||
margin_right = 92.0
|
||||
margin_bottom = 15.0
|
||||
text = "Platform angle"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/PlatformAngle"]
|
||||
margin_left = 112.0
|
||||
margin_right = 312.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 200, 0 )
|
||||
max_value = 360.0
|
||||
script = ExtResource( 5 )
|
||||
snap_step = 5.0
|
||||
|
||||
[node name="LabelValue" type="Label" parent="Controls/PlatformAngle"]
|
||||
margin_left = 332.0
|
||||
margin_top = 1.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 15.0
|
||||
rect_min_size = Vector2( 100, 0 )
|
||||
text = "0.0"
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="BodyAngle" type="HBoxContainer" parent="Controls"]
|
||||
margin_top = 52.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 68.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/BodyAngle"]
|
||||
margin_left = 22.0
|
||||
margin_top = 1.0
|
||||
margin_right = 92.0
|
||||
margin_bottom = 15.0
|
||||
text = "Body angle"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/BodyAngle"]
|
||||
margin_left = 112.0
|
||||
margin_right = 312.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 200, 0 )
|
||||
max_value = 360.0
|
||||
script = ExtResource( 5 )
|
||||
snap_step = 5.0
|
||||
|
||||
[node name="LabelValue" type="Label" parent="Controls/BodyAngle"]
|
||||
margin_left = 332.0
|
||||
margin_top = 1.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 15.0
|
||||
rect_min_size = Vector2( 100, 0 )
|
||||
text = "0.0"
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="LabelResultTitle" type="Label" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = 34.1273
|
||||
margin_top = 251.131
|
||||
margin_right = 88.1273
|
||||
margin_bottom = 265.131
|
||||
text = "RESULT: "
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelResult" type="Label" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = 34.1273
|
||||
margin_top = 266.131
|
||||
margin_right = 88.1273
|
||||
margin_bottom = 280.131
|
||||
text = "..."
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelRestart" type="Label" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = 34.1273
|
||||
margin_top = 304.841
|
||||
margin_right = 139.127
|
||||
margin_bottom = 318.841
|
||||
text = "SPACE - RESTART"
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Timer" type="Timer" parent="."]
|
||||
wait_time = 5.0
|
||||
one_shot = true
|
||||
|
||||
[node name="TargetArea2D" type="Area2D" parent="."]
|
||||
position = Vector2( 724, 300 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="TargetArea2D"]
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="OneWayRigidBody2D" type="RigidBody2D" parent="."]
|
||||
position = Vector2( 512, 300 )
|
||||
mode = 3
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="OneWayRigidBody2D"]
|
||||
shape = SubResource( 2 )
|
||||
one_way_collision = true
|
||||
|
||||
[node name="RigidBody2D" type="RigidBody2D" parent="."]
|
||||
position = Vector2( 300, 300 )
|
||||
collision_mask = 2147483649
|
||||
gravity_scale = 0.0
|
||||
contacts_reported = 1
|
||||
contact_monitor = true
|
||||
|
||||
[node name="Sprite" type="Sprite" parent="RigidBody2D"]
|
||||
self_modulate = Color( 1, 1, 1, 0.501961 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBody2D"]
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="KinematicBody2D" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 300, 300 )
|
||||
collision_mask = 2147483649
|
||||
|
||||
[node name="Sprite" type="Sprite" parent="KinematicBody2D"]
|
||||
self_modulate = Color( 1, 1, 1, 0.501961 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="KinematicBody2D"]
|
||||
shape = SubResource( 3 )
|
||||
[connection signal="value_changed" from="Controls/PlatformSize/HSlider" to="." method="_set_platform_size"]
|
||||
[connection signal="value_changed" from="Controls/PlatformAngle/HSlider" to="." method="_set_platform_angle"]
|
||||
[connection signal="value_changed" from="Controls/BodyAngle/HSlider" to="." method="_set_rigidbody_angle"]
|
||||
7
2d/physics_tests/utils/label_slider_value.gd
Normal file
7
2d/physics_tests/utils/label_slider_value.gd
Normal file
@@ -0,0 +1,7 @@
|
||||
extends Label
|
||||
tool
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
var slider = get_node("../HSlider")
|
||||
text = "%.1f" % slider.value
|
||||
@@ -6,7 +6,7 @@ signal option_selected(item_path)
|
||||
signal option_changed(item_path, checked)
|
||||
|
||||
|
||||
func add_menu_item(item_path, checkbox = false, checked = false):
|
||||
func add_menu_item(item_path, checkbox = false, checked = false, radio = false):
|
||||
var path_elements = item_path.split("/", false)
|
||||
var path_element_count = path_elements.size()
|
||||
assert(path_element_count > 0)
|
||||
@@ -19,7 +19,10 @@ func add_menu_item(item_path, checkbox = false, checked = false):
|
||||
popup = _add_popup(popup, path, popup_label)
|
||||
|
||||
var label = path_elements[path_element_count - 1]
|
||||
if checkbox:
|
||||
if radio:
|
||||
popup.add_radio_check_item(label)
|
||||
popup.set_item_checked(popup.get_item_count() - 1, checked)
|
||||
elif checkbox:
|
||||
popup.add_check_item(label)
|
||||
popup.set_item_checked(popup.get_item_count() - 1, checked)
|
||||
else:
|
||||
@@ -52,7 +55,15 @@ 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)
|
||||
|
||||
if popup_menu.is_item_checkable(item_index):
|
||||
if popup_menu.is_item_radio_checkable(item_index):
|
||||
var checked = popup_menu.is_item_checked(item_index)
|
||||
if not checked:
|
||||
popup_menu.set_item_checked(item_index, true)
|
||||
for other_index in popup_menu.get_item_count():
|
||||
if other_index != item_index:
|
||||
popup_menu.set_item_checked(other_index, false)
|
||||
emit_signal("option_selected", item_path)
|
||||
elif 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)
|
||||
|
||||
11
2d/physics_tests/utils/slider.gd
Normal file
11
2d/physics_tests/utils/slider.gd
Normal file
@@ -0,0 +1,11 @@
|
||||
extends Slider
|
||||
|
||||
|
||||
export(float) var snap_step = 1.0
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if Input.is_key_pressed(KEY_SHIFT):
|
||||
step = 0.1
|
||||
else:
|
||||
step = snap_step
|
||||
Reference in New Issue
Block a user