diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 44673e7224cc..1647b0e260cd 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -672,6 +672,7 @@ void Node3DEditorViewport::cancel_transform() { sp->set_global_transform(se->original); } + collision_reposition = false; finish_transform(); set_message(TTR("Transform Aborted."), 3); } @@ -1801,7 +1802,7 @@ void Node3DEditorViewport::_sinput(const Ref &p_event) { if (b->is_pressed()) { clicked_wants_append = b->is_shift_pressed(); - if (_edit.mode != TRANSFORM_NONE && _edit.instant) { + if (_edit.mode != TRANSFORM_NONE && (_edit.instant || collision_reposition)) { commit_transform(); break; // just commit the edit, stop processing the event so we don't deselect the object } @@ -2400,10 +2401,10 @@ void Node3DEditorViewport::_sinput(const Ref &p_event) { cancel_transform(); } if (!is_freelook_active() && !k->is_echo()) { - if (ED_IS_SHORTCUT("spatial_editor/instant_translate", p_event) && _edit.mode != TRANSFORM_TRANSLATE) { + if (ED_IS_SHORTCUT("spatial_editor/instant_translate", p_event) && (_edit.mode != TRANSFORM_TRANSLATE || collision_reposition)) { if (_edit.mode == TRANSFORM_NONE) { begin_transform(TRANSFORM_TRANSLATE, true); - } else if (_edit.instant) { + } else if (_edit.instant || collision_reposition) { commit_transform(); begin_transform(TRANSFORM_TRANSLATE, true); } @@ -2411,7 +2412,7 @@ void Node3DEditorViewport::_sinput(const Ref &p_event) { if (ED_IS_SHORTCUT("spatial_editor/instant_rotate", p_event) && _edit.mode != TRANSFORM_ROTATE) { if (_edit.mode == TRANSFORM_NONE) { begin_transform(TRANSFORM_ROTATE, true); - } else if (_edit.instant) { + } else if (_edit.instant || collision_reposition) { commit_transform(); begin_transform(TRANSFORM_ROTATE, true); } @@ -2419,11 +2420,24 @@ void Node3DEditorViewport::_sinput(const Ref &p_event) { if (ED_IS_SHORTCUT("spatial_editor/instant_scale", p_event) && _edit.mode != TRANSFORM_SCALE) { if (_edit.mode == TRANSFORM_NONE) { begin_transform(TRANSFORM_SCALE, true); - } else if (_edit.instant) { + } else if (_edit.instant || collision_reposition) { commit_transform(); begin_transform(TRANSFORM_SCALE, true); } } + if (ED_IS_SHORTCUT("spatial_editor/collision_reposition", p_event) && editor_selection->get_selected_node_list().size() == 1 && !collision_reposition) { + if (_edit.mode == TRANSFORM_NONE || _edit.instant) { + if (_edit.mode == TRANSFORM_NONE) { + _compute_edit(_edit.mouse_pos); + } else { + commit_transform(); + _compute_edit(_edit.mouse_pos); + } + _edit.mode = TRANSFORM_TRANSLATE; + collision_reposition = true; + } + } + } // Freelook doesn't work in orthogonal mode. @@ -3074,6 +3088,19 @@ void Node3DEditorViewport::_notification(int p_what) { } break; case NOTIFICATION_PHYSICS_PROCESS: { + if (collision_reposition) { + List &selection = editor_selection->get_selected_node_list(); + + if (selection.size() == 1) { + Node3D *first_selected_node = Object::cast_to(selection.front()->get()); + double snap = EDITOR_GET("interface/inspector/default_float_step"); + int snap_step_decimals = Math::range_step_decimals(snap); + set_message(TTR("Translating:") + " (" + String::num(first_selected_node->get_global_position().x, snap_step_decimals) + ", " + + String::num(first_selected_node->get_global_position().y, snap_step_decimals) + ", " + String::num(first_selected_node->get_global_position().z, snap_step_decimals) + ")"); + first_selected_node->set_global_position(spatial_editor->snap_point(_get_instance_position(_edit.mouse_pos))); + } + } + if (!update_preview_node) { return; } @@ -3968,7 +3995,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() { return; } - bool show_gizmo = spatial_editor->is_gizmo_visible() && !_edit.instant && transform_gizmo_visible; + bool show_gizmo = spatial_editor->is_gizmo_visible() && !_edit.instant && transform_gizmo_visible && !collision_reposition; for (int i = 0; i < 3; i++) { Transform3D axis_angle; if (xform.basis.get_column(i).normalized().dot(xform.basis.get_column((i + 1) % 3).normalized()) < 1.0) { @@ -4243,6 +4270,18 @@ void Node3DEditorViewport::assign_pending_data_pointers(Node3D *p_preview_node, accept = p_accept; } +void _insert_rid_recursive(Node *node, HashSet &rids) { + CollisionObject3D *co = Object::cast_to(node); + if (co) { + rids.insert(co->get_rid()); + } + + for (int i = 0; i < node->get_child_count(); i++) { + Node *child = node->get_child(i); + _insert_rid_recursive(child, rids); + } +} + Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const { const float MAX_DISTANCE = 50.0; const float FALLBACK_DISTANCE = 5.0; @@ -4252,7 +4291,22 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const PhysicsDirectSpaceState3D *ss = get_tree()->get_root()->get_world_3d()->get_direct_space_state(); + HashSet rids; + + if (!preview_node->is_inside_tree()) { + List &selection = editor_selection->get_selected_node_list(); + + Node3D *first_selected_node = Object::cast_to(selection.front()->get()); + + Array children = first_selected_node->get_children(); + + if (first_selected_node) { + _insert_rid_recursive(first_selected_node, rids); + } + } + PhysicsDirectSpaceState3D::RayParameters ray_params; + ray_params.exclude = rids; ray_params.from = world_pos; ray_params.to = world_pos + world_ray * camera->get_far(); @@ -4880,6 +4934,7 @@ void Node3DEditorViewport::commit_transform() { } undo_redo->commit_action(); + collision_reposition = false; finish_transform(); set_message(""); } @@ -5477,6 +5532,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p ED_SHORTCUT("spatial_editor/instant_translate", TTR("Begin Translate Transformation")); ED_SHORTCUT("spatial_editor/instant_rotate", TTR("Begin Rotate Transformation")); ED_SHORTCUT("spatial_editor/instant_scale", TTR("Begin Scale Transformation")); + ED_SHORTCUT("spatial_editor/collision_reposition", TTR("Reposition Using Collisions")); preview_camera = memnew(CheckBox); preview_camera->set_text(TTR("Preview")); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 2cfe784ca688..f76169dd13cb 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -245,6 +245,7 @@ class Node3DEditorViewport : public Control { bool auto_orthogonal; bool lock_rotation; bool transform_gizmo_visible = true; + bool collision_reposition = false; real_t gizmo_scale; bool freelook_active; @@ -338,7 +339,6 @@ class Node3DEditorViewport : public Control { TRANSFORM_ROTATE, TRANSFORM_TRANSLATE, TRANSFORM_SCALE - }; enum TransformPlane { TRANSFORM_VIEW,