diff --git a/editor/scene/2d/physics/collision_shape_2d_editor_plugin.cpp b/editor/scene/2d/physics/collision_shape_2d_editor_plugin.cpp index 16aa2d6dc7d..495c024a1ed 100644 --- a/editor/scene/2d/physics/collision_shape_2d_editor_plugin.cpp +++ b/editor/scene/2d/physics/collision_shape_2d_editor_plugin.cpp @@ -389,17 +389,30 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref &p_e return true; - } else { - if (pressed) { - if (original_mouse_pos != gpoint) { - commit_handle(edit_handle, original); - } - - edit_handle = -1; - pressed = false; - - return true; + } else if (pressed) { + Ref m = p_event; + if (m.is_valid() && original_mouse_pos != m->get_position()) { + commit_handle(edit_handle, original); } + + edit_handle = -1; + pressed = false; + + return true; + } + } else if (pressed) { + // Cancel the drag. + if (ED_IS_SHORTCUT("canvas_item_editor/cancel_transform", p_event) || + (mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT)) { + Ref m = p_event; + if (m.is_valid() && original_mouse_pos != m->get_position()) { + set_handle(edit_handle, original_point); + } + + edit_handle = -1; + pressed = false; + + return true; } } @@ -624,6 +637,16 @@ void CollisionShape2DEditor::_notification(int p_what) { grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); } } break; + + case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { + // Commit the drag if the window is focused out. + if (pressed && edit_handle > 0) { + commit_handle(edit_handle, original); + + edit_handle = -1; + pressed = false; + } + } break; } } diff --git a/editor/scene/3d/node_3d_editor_plugin.cpp b/editor/scene/3d/node_3d_editor_plugin.cpp index 7c4a9d83ffd..c8fbd3817b6 100644 --- a/editor/scene/3d/node_3d_editor_plugin.cpp +++ b/editor/scene/3d/node_3d_editor_plugin.cpp @@ -3496,6 +3496,22 @@ void Node3DEditorViewport::_notification(int p_what) { set_freelook_active(false); cursor.region_select = false; surface->queue_redraw(); + + // Commit the drag if the window is focused out. + if (_edit.mode != TRANSFORM_NONE) { + commit_transform(); + return; + } + + if (_edit.gizmo.is_valid()) { + // Certain gizmo plugins should be able to commit handles without dragging them. + if (_edit.original_mouse_pos != _edit.mouse_pos || _edit.gizmo->get_plugin()->can_commit_handle_on_click()) { + _edit.gizmo->commit_handle(_edit.gizmo_handle, _edit.gizmo_handle_secondary, _edit.gizmo_initial_value, false); + } + + spatial_editor->get_single_selected_node()->update_gizmos(); + _edit.gizmo = Ref(); + } } break; case NOTIFICATION_ENTER_TREE: { diff --git a/editor/scene/canvas_item_editor_plugin.cpp b/editor/scene/canvas_item_editor_plugin.cpp index f802c5f75ce..eb8127facc0 100644 --- a/editor/scene/canvas_item_editor_plugin.cpp +++ b/editor/scene/canvas_item_editor_plugin.cpp @@ -1523,14 +1523,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref &p_event) { if (drag_selection.size() >= 1 && ((b.is_valid() && !b->is_pressed() && b->get_button_index() == MouseButton::LEFT && tool == TOOL_EDIT_PIVOT) || (k.is_valid() && !k->is_pressed() && k->get_keycode() == Key::V))) { - _commit_canvas_item_state( - drag_selection, - vformat( - TTR("Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"), - drag_selection.front()->get()->get_name(), - drag_selection.front()->get()->_edit_get_pivot().x, - drag_selection.front()->get()->_edit_get_pivot().y)); - _reset_drag(); + _commit_drag(); return true; } @@ -1628,25 +1621,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref &p_event) { // Confirms the node rotation if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && !b->is_pressed()) { - if (drag_selection.size() != 1) { - _commit_canvas_item_state( - drag_selection, - vformat(TTR("Rotate %d CanvasItems"), drag_selection.size()), - true); - } else { - _commit_canvas_item_state( - drag_selection, - vformat(TTR("Rotate CanvasItem \"%s\" to %d degrees"), - drag_selection.front()->get()->get_name(), - Math::rad_to_deg(drag_selection.front()->get()->_edit_get_rotation())), - true); - } - - if (key_auto_insert_button->is_pressed()) { - _insert_animation_keys(false, true, false, true); - } - - _reset_drag(); + _commit_drag(); return true; } @@ -1805,13 +1780,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref &p_event) { // Confirms new anchor position if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MouseButton::LEFT && !b->is_pressed()) { - _commit_canvas_item_state( - drag_selection, - vformat(TTR("Move CanvasItem \"%s\" Anchor"), drag_selection.front()->get()->get_name())); - snap_target[0] = SNAP_TARGET_NONE; - snap_target[1] = SNAP_TARGET_NONE; - _reset_drag(); - viewport->queue_redraw(); + _commit_drag(); return true; } @@ -1983,38 +1952,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref &p_event) { // Confirm resize if (drag_selection.size() >= 1 && b.is_valid() && b->get_button_index() == MouseButton::LEFT && !b->is_pressed()) { - const Node2D *node2d = Object::cast_to(drag_selection.front()->get()); - if (node2d) { - // Extends from Node2D. - // Node2D doesn't have an actual stored rect size, unlike Controls. - _commit_canvas_item_state( - drag_selection, - vformat( - TTR("Scale Node2D \"%s\" to (%s, %s)"), - drag_selection.front()->get()->get_name(), - Math::snapped(drag_selection.front()->get()->_edit_get_scale().x, 0.01), - Math::snapped(drag_selection.front()->get()->_edit_get_scale().y, 0.01)), - true); - } else { - // Extends from Control. - _commit_canvas_item_state( - drag_selection, - vformat( - TTR("Resize Control \"%s\" to (%d, %d)"), - drag_selection.front()->get()->get_name(), - drag_selection.front()->get()->_edit_get_rect().size.x, - drag_selection.front()->get()->_edit_get_rect().size.y), - true); - } - - if (key_auto_insert_button->is_pressed()) { - _insert_animation_keys(false, false, true, true); - } - - snap_target[0] = SNAP_TARGET_NONE; - snap_target[1] = SNAP_TARGET_NONE; - _reset_drag(); - viewport->queue_redraw(); + _commit_drag(); return true; } @@ -2180,26 +2118,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref &p_event) { // Confirm resize if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && !b->is_pressed()) { - if (drag_selection.size() != 1) { - _commit_canvas_item_state( - drag_selection, - vformat(TTR("Scale %d CanvasItems"), drag_selection.size()), - true); - } else { - _commit_canvas_item_state( - drag_selection, - vformat(TTR("Scale CanvasItem \"%s\" to (%s, %s)"), - drag_selection.front()->get()->get_name(), - Math::snapped(drag_selection.front()->get()->_edit_get_scale().x, 0.01), - Math::snapped(drag_selection.front()->get()->_edit_get_scale().y, 0.01)), - true); - } - if (key_auto_insert_button->is_pressed()) { - _insert_animation_keys(false, false, true, true); - } - - _reset_drag(); - viewport->queue_redraw(); + _commit_drag(); return true; } @@ -2316,34 +2235,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref &p_event) { // Confirm the move (only if it was moved) if (b.is_valid() && !b->is_pressed() && b->get_button_index() == MouseButton::LEFT) { - if (transform.affine_inverse().xform(b->get_position()) != drag_from) { - if (drag_selection.size() != 1) { - _commit_canvas_item_state( - drag_selection, - vformat(TTR("Move %d CanvasItems"), drag_selection.size()), - true); - } else { - _commit_canvas_item_state( - drag_selection, - vformat( - TTR("Move CanvasItem \"%s\" to (%d, %d)"), - drag_selection.front()->get()->get_name(), - drag_selection.front()->get()->_edit_get_position().x, - drag_selection.front()->get()->_edit_get_position().y), - true); - } - } - - if (key_auto_insert_button->is_pressed()) { - _insert_animation_keys(true, false, false, true); - } - - //Make sure smart snapping lines disappear. - snap_target[0] = SNAP_TARGET_NONE; - snap_target[1] = SNAP_TARGET_NONE; - - _reset_drag(); - viewport->queue_redraw(); + _commit_drag(); return true; } @@ -2435,30 +2327,10 @@ bool CanvasItemEditor::_gui_input_move(const Ref &p_event) { return true; } + // Confirm canvas items move by arrow keys. if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && (tool == TOOL_SELECT || tool == TOOL_MOVE) && (k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::LEFT || k->get_keycode() == Key::RIGHT)) { - // Confirm canvas items move by arrow keys - if ((!Input::get_singleton()->is_key_pressed(Key::UP)) && - (!Input::get_singleton()->is_key_pressed(Key::DOWN)) && - (!Input::get_singleton()->is_key_pressed(Key::LEFT)) && - (!Input::get_singleton()->is_key_pressed(Key::RIGHT))) { - if (drag_selection.size() > 1) { - _commit_canvas_item_state( - drag_selection, - vformat(TTR("Move %d CanvasItems"), drag_selection.size()), - true); - } else if (drag_selection.size() == 1) { - _commit_canvas_item_state( - drag_selection, - vformat(TTR("Move CanvasItem \"%s\" to (%d, %d)"), - drag_selection.front()->get()->get_name(), - drag_selection.front()->get()->_edit_get_position().x, - drag_selection.front()->get()->_edit_get_position().y), - true); - } - _reset_drag(); - } - viewport->queue_redraw(); + _commit_drag(); return true; } @@ -2863,6 +2735,183 @@ void CanvasItemEditor::_gui_input_viewport(const Ref &p_event) { } } +void CanvasItemEditor::_commit_drag() { + if (drag_selection.is_empty()) { + return; + } + + switch (drag_type) { + // Confirm the pivot move. + case DRAG_PIVOT: { + _commit_canvas_item_state( + drag_selection, + vformat( + TTR("Set CanvasItem \"%s\" Pivot Offset to (%d, %d)"), + drag_selection.front()->get()->get_name(), + drag_selection.front()->get()->_edit_get_pivot().x, + drag_selection.front()->get()->_edit_get_pivot().y)); + } break; + + // Confirm the node rotation. + case DRAG_ROTATE: { + if (drag_selection.size() != 1) { + _commit_canvas_item_state( + drag_selection, + vformat(TTR("Rotate %d CanvasItems"), drag_selection.size()), + true); + } else { + _commit_canvas_item_state( + drag_selection, + vformat(TTR("Rotate CanvasItem \"%s\" to %d degrees"), + drag_selection.front()->get()->get_name(), + Math::rad_to_deg(drag_selection.front()->get()->_edit_get_rotation())), + true); + } + + if (key_auto_insert_button->is_pressed()) { + _insert_animation_keys(false, true, false, true); + } + } break; + + // Confirm new anchor position. + case DRAG_ANCHOR_TOP_LEFT: + case DRAG_ANCHOR_TOP_RIGHT: + case DRAG_ANCHOR_BOTTOM_RIGHT: + case DRAG_ANCHOR_BOTTOM_LEFT: + case DRAG_ANCHOR_ALL: { + _commit_canvas_item_state( + drag_selection, + vformat(TTR("Move CanvasItem \"%s\" Anchor"), drag_selection.front()->get()->get_name())); + snap_target[0] = SNAP_TARGET_NONE; + snap_target[1] = SNAP_TARGET_NONE; + } break; + + // Confirm resize. + case DRAG_LEFT: + case DRAG_RIGHT: + case DRAG_TOP: + case DRAG_BOTTOM: + case DRAG_TOP_LEFT: + case DRAG_TOP_RIGHT: + case DRAG_BOTTOM_LEFT: + case DRAG_BOTTOM_RIGHT: { + const Node2D *node2d = Object::cast_to(drag_selection.front()->get()); + if (node2d) { + // Extends from Node2D. + // Node2D doesn't have an actual stored rect size, unlike Controls. + _commit_canvas_item_state( + drag_selection, + vformat( + TTR("Scale Node2D \"%s\" to (%s, %s)"), + drag_selection.front()->get()->get_name(), + Math::snapped(drag_selection.front()->get()->_edit_get_scale().x, 0.01), + Math::snapped(drag_selection.front()->get()->_edit_get_scale().y, 0.01)), + true); + } else { + // Extends from Control. + _commit_canvas_item_state( + drag_selection, + vformat( + TTR("Resize Control \"%s\" to (%d, %d)"), + drag_selection.front()->get()->get_name(), + drag_selection.front()->get()->_edit_get_rect().size.x, + drag_selection.front()->get()->_edit_get_rect().size.y), + true); + } + + if (key_auto_insert_button->is_pressed()) { + _insert_animation_keys(false, false, true, true); + } + + snap_target[0] = SNAP_TARGET_NONE; + snap_target[1] = SNAP_TARGET_NONE; + } break; + + // Confirm resize. + case DRAG_SCALE_BOTH: + case DRAG_SCALE_X: + case DRAG_SCALE_Y: { + if (drag_selection.size() != 1) { + _commit_canvas_item_state( + drag_selection, + vformat(TTR("Scale %d CanvasItems"), drag_selection.size()), + true); + } else { + _commit_canvas_item_state( + drag_selection, + vformat(TTR("Scale CanvasItem \"%s\" to (%s, %s)"), + drag_selection.front()->get()->get_name(), + Math::snapped(drag_selection.front()->get()->_edit_get_scale().x, 0.01), + Math::snapped(drag_selection.front()->get()->_edit_get_scale().y, 0.01)), + true); + } + if (key_auto_insert_button->is_pressed()) { + _insert_animation_keys(false, false, true, true); + } + } break; + + // Confirm the canvas items move. + case DRAG_MOVE: + case DRAG_MOVE_X: + case DRAG_MOVE_Y: { + if (transform.affine_inverse().xform(get_viewport()->get_mouse_position()) != drag_from) { + if (drag_selection.size() != 1) { + _commit_canvas_item_state( + drag_selection, + vformat(TTR("Move %d CanvasItems"), drag_selection.size()), + true); + } else { + _commit_canvas_item_state( + drag_selection, + vformat( + TTR("Move CanvasItem \"%s\" to (%d, %d)"), + drag_selection.front()->get()->get_name(), + drag_selection.front()->get()->_edit_get_position().x, + drag_selection.front()->get()->_edit_get_position().y), + true); + } + } + + if (key_auto_insert_button->is_pressed()) { + _insert_animation_keys(true, false, false, true); + } + + // Make sure smart snapping lines disappear. + snap_target[0] = SNAP_TARGET_NONE; + snap_target[1] = SNAP_TARGET_NONE; + } break; + + // Confirm the canvas items move by arrow keys. + case DRAG_KEY_MOVE: { + if (tool != TOOL_SELECT && tool != TOOL_MOVE) { + return; + } + + if (drag_selection.size() > 1) { + _commit_canvas_item_state( + drag_selection, + vformat(TTR("Move %d CanvasItems"), drag_selection.size()), + true); + } else if (drag_selection.size() == 1) { + _commit_canvas_item_state( + drag_selection, + vformat(TTR("Move CanvasItem \"%s\" to (%d, %d)"), + drag_selection.front()->get()->get_name(), + drag_selection.front()->get()->_edit_get_position().x, + drag_selection.front()->get()->_edit_get_position().y), + true); + } + } break; + + default: + break; + } + + _reset_drag(); + viewport->queue_redraw(); + _update_cursor(); +} + void CanvasItemEditor::_update_cursor() { if (cursor_shape_override != CURSOR_ARROW) { set_default_cursor_shape(cursor_shape_override); @@ -4343,8 +4392,7 @@ void CanvasItemEditor::_notification(int p_what) { case NOTIFICATION_APPLICATION_FOCUS_OUT: case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { if (drag_type != DRAG_NONE) { - _reset_drag(); - viewport->queue_redraw(); + _commit_drag(); } } break; } diff --git a/editor/scene/canvas_item_editor_plugin.h b/editor/scene/canvas_item_editor_plugin.h index 06627a2f438..aeb30b7059c 100644 --- a/editor/scene/canvas_item_editor_plugin.h +++ b/editor/scene/canvas_item_editor_plugin.h @@ -492,6 +492,8 @@ private: bool _gui_input_rulers_and_guides(const Ref &p_event); bool _gui_input_hover(const Ref &p_event); + void _commit_drag(); + void _gui_input_viewport(const Ref &p_event); void _update_cursor(); void _update_lock_and_group_button();