How do I compensate for camera zoom when moving a node?

Godot Version

v4.4.1.stable.official [49a5bc7b6]

Question

I copied this code for dragging an object around the screen. It works fine, but if I increase the zoom of my Camera2D, the mouse pointer and the object (in my case a Path2D with an attached button) drift apart:

My Path2D’s script:

func _process(_delta: float) -> void:
	var mouse_position = get_viewport().get_mouse_position()
	if moving:
		position = mouse_position + dif
func _on_grab_button_button_down() -> void:
	cam_zoom = get_viewport().get_camera_2d().zoom
	dif = position - get_viewport().get_mouse_position()
	if Input.get_mouse_button_mask() == 1:
		moving = true

I tried to work the zoom into the script at different places, but can’t get the pointer to stay with the object. Help please!

CanvasItem.get_global_mouse_position returns the mouse position with position and zoom of the camera already accounted for.

This is how I would write the whole thing:

@onready var camera: Camera2D = get_viewport().get_camera_2d() # only works if there is only ever one main camera

var mouse_pos_buffer: Vector2

func _process(_delta: float) -> void:
	if Input.is_action_just_pressed("drag"):
		mouse_pos_buffer = get_global_mouse_position() - camera.position # subtract camera position because the camera moves
	if Input.is_action_pressed("drag"):
		_drag()

func _drag() -> void:
	var new_mouse_pos: Vector2 = get_global_mouse_position() - camera.position
	camera.position -= new_mouse_pos - mouse_pos_buffer
	mouse_pos_buffer = new_mouse_pos
2 Likes

@yesko Thank you! get_global_mouse_position() did the trick:

func _process(_delta: float) -> void:
	var mouse_position = get_global_mouse_position()
	if moving:
		position = mouse_position + dif

and

func _on_grab_button_button_down() -> void:
	dif = position - get_global_mouse_position()
	if Input.get_mouse_button_mask() == 1:
		moving = true
1 Like