Repository: godotengine/godot
File: editor/plugins/canvas_item_editor_plugin.cpp (C++)

Code before:
		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[0]->get_name(),
							drag_selection[0]->_edit_get_pivot().x,
							drag_selection[0]->_edit_get_pivot().y));
			_reset_drag();
			return true;
		}

		// Cancel a drag
		if (ED_IS_SHORTCUT("canvas_item_editor/cancel_transform", p_event) || (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed())) {
			_restore_canvas_item_state(drag_selection);
			_reset_drag();
			viewport->queue_redraw();
			return true;
		}
	}
	return false;
}

bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
	Ref<InputEventMouseButton> b = p_event;
	Ref<InputEventMouseMotion> m = p_event;

	// Start rotation
	if (drag_type == DRAG_NONE) {
		if (b.is_valid() && b->get_button_index() == MouseButton::LEFT && b->is_pressed()) {
			if ((b->is_command_or_control_pressed() && !b->is_alt_pressed() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
				List<CanvasItem *> selection = _get_edited_canvas_items();

				// Remove not movable nodes
				for (CanvasItem *E : selection) {
					if (!_is_node_movable(E, true)) {
						selection.erase(E);
					}
				}

				drag_selection = selection;
				if (drag_selection.size() > 0) {
					drag_type = DRAG_ROTATE;
					drag_from = transform.affine_inverse().xform(b->get_position());
					CanvasItem *ci = drag_selection[0];
					if (ci->_edit_use_pivot()) {
						drag_rotation_center = ci->get_global_transform_with_canvas().xform(ci->_edit_get_pivot());
					} else {
						drag_rotation_center = ci->get_global_transform_with_canvas().get_origin();

Review comment (suggestion):
I'm not sure you can rely on this to work in a floating point comparison. That's why we have to use things like `isinf()` instead of equality operators for scalars, so that's probably the same for vectors.

Code after:
				new_pos = snap_point(drag_to, SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, drag_selection[0]);
			} else {
				new_pos = snap_point(drag_to, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL);
			}
			for (CanvasItem *ci : drag_selection) {
				ci->_edit_set_pivot(ci->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
			}
			return true;
		}

		// Confirm the pivot move
		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[0]->get_name(),
							drag_selection[0]->_edit_get_pivot().x,
							drag_selection[0]->_edit_get_pivot().y));
			_reset_drag();
			return true;
		}

		// Cancel a drag
		if (ED_IS_SHORTCUT("canvas_item_editor/cancel_transform", p_event) || (b.is_valid() && b->get_button_index() == MouseButton::RIGHT && b->is_pressed())) {
			_restore_canvas_item_state(drag_selection);
			_reset_drag();
			viewport->queue_redraw();
			return true;
		}
	}

	if (drag_type == DRAG_TEMP_PIVOT) {
		if (m.is_valid()) {
			temp_pivot = transform.affine_inverse().xform(m->get_position());
			viewport->queue_redraw();
			return true;
		}

		if ((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)) {
			drag_type = DRAG_NONE;
			return true;
		}
	}
	return false;
}

bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {