diff --git a/2d/physics_tests/test.gd b/2d/physics_tests/test.gd index 8242f6528d..1dfc8c17b4 100644 --- a/2d/physics_tests/test.gd +++ b/2d/physics_tests/test.gd @@ -22,9 +22,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") @@ -61,17 +61,28 @@ func clear_drawn_nodes(): _drawn_nodes.clear() -func create_rigidbody_box(size): - var template_shape = RectangleShape2D.new() - template_shape.extents = 0.5 * size +func create_rigidbody_box(size, pickable = false, use_icon = false): + var shape = RectangleShape2D.new() + shape.extents = 0.5 * size - var template_collision = CollisionShape2D.new() - template_collision.shape = template_shape + var collision = CollisionShape2D.new() + collision.shape = shape + + var body = RigidBody2D.new() + body.add_child(collision) + + if pickable: + var script = load("res://utils/rigidbody_pick.gd") + body.set_script(script) - var template_body = RigidBody2D.new() - template_body.add_child(template_collision) + if use_icon: + var texture = load("res://icon.png") + var icon = Sprite.new() + icon.texture = texture + icon.scale = size / texture.get_size() + body.add_child(icon) - return template_body + return body func start_timer(timeout): diff --git a/2d/physics_tests/tests.gd b/2d/physics_tests/tests.gd index de1e12d64b..cd735be864 100644 --- a/2d/physics_tests/tests.gd +++ b/2d/physics_tests/tests.gd @@ -18,6 +18,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", diff --git a/2d/physics_tests/tests/functional/test_collision_pairs.gd b/2d/physics_tests/tests/functional/test_collision_pairs.gd index a00980602c..0fbe81d85e 100644 --- a/2d/physics_tests/tests/functional/test_collision_pairs.gd +++ b/2d/physics_tests/tests/functional/test_collision_pairs.gd @@ -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_RECTANGLE) - 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_CONVEX_POLYGON) - elif (key_event.scancode == KEY_5): + elif key_event.scancode == KEY_5: _on_option_selected(OPTION_TYPE_CONCAVE_SEGMENTS) diff --git a/2d/physics_tests/tests/functional/test_joints.gd b/2d/physics_tests/tests/functional/test_joints.gd new file mode 100644 index 0000000000..155a16b426 --- /dev/null +++ b/2d/physics_tests/tests/functional/test_joints.gd @@ -0,0 +1,140 @@ +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 = Vector2(64, 64) + +var _update_joint = false +var _selected_joint = null + +var _joint_type = PinJoint2D +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() - 7) + 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, true) + child_body.mode = RigidBody2D.MODE_RIGID + if _change_positions: + root.add_child(child_body) + child_body.position = Vector2(0.0, 40) + else: + child_body.position = Vector2(0.0, 40) + root.add_child(child_body) + + var parent_body = null + if not _world_attachement: + parent_body = create_rigidbody_box(BOX_SIZE, true, true) + if _dynamic_attachement: + parent_body.mode = RigidBody2D.MODE_RIGID + parent_body.gravity_scale = 0.0 + child_body.gravity_scale = 0.0 + else: + parent_body.mode = RigidBody2D.MODE_STATIC + if _change_positions: + root.add_child(parent_body) + parent_body.position = Vector2(0.0, -40) + else: + parent_body.position = Vector2(0.0, -40) + root.add_child(parent_body) + + var joint = _selected_joint.duplicate() + joint.visible = true + joint.disable_collision = not _bodies_collide + if parent_body: + joint.node_a = parent_body.get_path() + joint.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() diff --git a/2d/physics_tests/tests/functional/test_joints.tscn b/2d/physics_tests/tests/functional/test_joints.tscn new file mode 100644 index 0000000000..411273e29e --- /dev/null +++ b/2d/physics_tests/tests/functional/test_joints.tscn @@ -0,0 +1,31 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://tests/functional/test_joints.gd" type="Script" id=2] +[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=4] + +[node name="JointTest2D" type="Node2D"] +script = ExtResource( 2 ) + +[node name="LabelJointType" type="Label" parent="."] +margin_left = 14.0 +margin_top = 79.0 +margin_right = 145.0 +margin_bottom = 93.0 +text = "Joint Type: " +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Options" parent="." instance=ExtResource( 4 )] + +[node name="Joints" type="Node2D" parent="."] +position = Vector2( 512, 200 ) + +[node name="PinJoint2D" type="PinJoint2D" parent="Joints"] + +[node name="DampedSpringJoint2D" type="DampedSpringJoint2D" parent="Joints"] + +[node name="GrooveJoint2D" type="GrooveJoint2D" parent="Joints"] + +[node name="Objects" type="Node2D" parent="."] +position = Vector2( 512, 200 ) diff --git a/2d/physics_tests/tests/functional/test_pyramid.gd b/2d/physics_tests/tests/functional/test_pyramid.gd index 8291b246ac..bd0bcfb3f9 100644 --- a/2d/physics_tests/tests/functional/test_pyramid.gd +++ b/2d/physics_tests/tests/functional/test_pyramid.gd @@ -13,7 +13,7 @@ func _ready(): func _create_pyramid(): var root_node = $Pyramid - var template_body = create_rigidbody_box(box_size) + var template_body = create_rigidbody_box(box_size, true) var pos_y = -0.5 * box_size.y - box_spacing.y diff --git a/2d/physics_tests/tests/functional/test_stack.gd b/2d/physics_tests/tests/functional/test_stack.gd index 7198b589c5..e1d2ed3366 100644 --- a/2d/physics_tests/tests/functional/test_stack.gd +++ b/2d/physics_tests/tests/functional/test_stack.gd @@ -14,7 +14,7 @@ func _ready(): func _create_stack(): var root_node = $Stack - var template_body = create_rigidbody_box(box_size) + var template_body = create_rigidbody_box(box_size, true) var pos_y = -0.5 * box_size.y - box_spacing.y diff --git a/2d/physics_tests/utils/rigidbody_pick.gd b/2d/physics_tests/utils/rigidbody_pick.gd new file mode 100644 index 0000000000..318fcc68f1 --- /dev/null +++ b/2d/physics_tests/utils/rigidbody_pick.gd @@ -0,0 +1,32 @@ +extends RigidBody2D + + +var _picked = false +var _last_mouse_pos = Vector2.ZERO + + +func _ready(): + input_pickable = true + + +func _input(event): + var mouse_event = event as InputEventMouseButton + if mouse_event and not mouse_event.pressed: + _picked = false + + +func _input_event(_viewport, event, _shape_idx): + var mouse_event = event as InputEventMouseButton + if mouse_event and mouse_event.pressed: + _picked = true + _last_mouse_pos = get_global_mouse_position() + + +func _physics_process(delta): + if _picked: + var mouse_pos = get_global_mouse_position() + if mode == MODE_STATIC: + global_position = mouse_pos + else: + linear_velocity = (mouse_pos - _last_mouse_pos) / delta + _last_mouse_pos = mouse_pos diff --git a/3d/physics_tests/test.gd b/3d/physics_tests/test.gd index b1a7a2ee4f..6149522fe3 100644 --- a/3d/physics_tests/test.gd +++ b/3d/physics_tests/test.gd @@ -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 body = RigidBody.new() + body.add_child(collision) - var template_body = RigidBody.new() - template_body.add_child(template_collision) + if pickable: + var script = load("res://utils/rigidbody_pick.gd") + body.set_script(script) - return template_body + return body func start_timer(timeout): diff --git a/3d/physics_tests/tests.gd b/3d/physics_tests/tests.gd index 7d6ad38830..68bd25862a 100644 --- a/3d/physics_tests/tests.gd +++ b/3d/physics_tests/tests.gd @@ -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", diff --git a/3d/physics_tests/tests/functional/test_collision_pairs.gd b/3d/physics_tests/tests/functional/test_collision_pairs.gd index b6f113c080..19b58bcb2b 100644 --- a/3d/physics_tests/tests/functional/test_collision_pairs.gd +++ b/3d/physics_tests/tests/functional/test_collision_pairs.gd @@ -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) diff --git a/3d/physics_tests/tests/functional/test_joints.gd b/3d/physics_tests/tests/functional/test_joints.gd new file mode 100644 index 0000000000..2a8316acef --- /dev/null +++ b/3d/physics_tests/tests/functional/test_joints.gd @@ -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() diff --git a/3d/physics_tests/tests/functional/test_joints.tscn b/3d/physics_tests/tests/functional/test_joints.tscn new file mode 100644 index 0000000000..bdd4f0e67e --- /dev/null +++ b/3d/physics_tests/tests/functional/test_joints.tscn @@ -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 diff --git a/3d/physics_tests/tests/functional/test_pyramid.gd b/3d/physics_tests/tests/functional/test_pyramid.gd index 673d35cde0..19e7bd522c 100644 --- a/3d/physics_tests/tests/functional/test_pyramid.gd +++ b/3d/physics_tests/tests/functional/test_pyramid.gd @@ -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 diff --git a/3d/physics_tests/tests/functional/test_stack.gd b/3d/physics_tests/tests/functional/test_stack.gd index 0af325c4dd..f0afe44e9b 100644 --- a/3d/physics_tests/tests/functional/test_stack.gd +++ b/3d/physics_tests/tests/functional/test_stack.gd @@ -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 diff --git a/3d/physics_tests/utils/camera_orbit.gd b/3d/physics_tests/utils/camera_orbit.gd index b918c87665..3e57983ab7 100644 --- a/3d/physics_tests/utils/camera_orbit.gd +++ b/3d/physics_tests/utils/camera_orbit.gd @@ -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 diff --git a/3d/physics_tests/utils/rigidbody_pick.gd b/3d/physics_tests/utils/rigidbody_pick.gd new file mode 100644 index 0000000000..948b2a6c15 --- /dev/null +++ b/3d/physics_tests/utils/rigidbody_pick.gd @@ -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