Global position returns incorrect value if camera2d is added to scene

Godot Version

4.2

Question

Hello,

I am trying to create a RTS like selector (drag and draw box). And it was working fine until I added the camera2d with zoom element, I changed the code, I will attach it below.

It kinda works, but it draws the selector box in a wrong place. It correctly considers endpoint and follows the mouse until button is released, but starting point is being set incorrectly. It seems that it now sets the first click as a starting point as well. Here is the code:

func _input(event): 
	if event is InputEventMouseButton and isDrawing == true:
		var transformed_position = get_viewport().get_canvas_transform().affine_inverse() * event.global_position
		if event.button_index == 1 and event.is_pressed():
			if !mouse_down:
				mouse_down = true
				self.visible = true
				mouse_start_pos = transformed_position
				$'.'.global_position = mouse_start_pos
		elif !event.is_pressed():
			if mouse_down:
				mouse_down = false
				pressed_ended()
				mouse_end_pos = transformed_position
				size = Vector2.ZERO
	if event is InputEventMouseMotion:
		if mouse_down:
			_update()
		
		
func _update():
	if get_global_mouse_position().x < mouse_start_pos.x:
		scale.x = -1
	if get_global_mouse_position().x > mouse_start_pos.x:
		scale.x = 1
	if get_global_mouse_position().y < mouse_start_pos.y:
		scale.y = -1
	elif get_global_mouse_position().y > mouse_start_pos.y:
		scale.y = 1
		
	size = (get_global_mouse_position() - mouse_start_pos)*scale

func pressed_ended():
	var nodes_to_get = get_tree().get_nodes_in_group(current_group)
	if nodes_to_get != null:
		for node in nodes_to_get:
			if get_global_rect().has_point(node.global_position):
				if node.status == current_status:
					nodes_in_rect.append(node)
					SendClientData()
					isDrawing = false
					self.visible = false

Thanks a lot in advance for any advice.

Note, that Camera2D works by adjusting the Viewports canvas_transform.
So if you change Camera2D during the time inverval between mouse-button-pressed and mouse-button-released, then $'.'.global_position = mouse_start_pos becomes problematic, because

  • mouse_start_pos is related to the Camera2D at the time when the mouse button was pressed.
  • $'.'.global_position is related to the Camera2D at the current time.

The following line can become problematic, if you use embedded Windows or SubViewports:

  • var transformed_position = get_viewport().get_canvas_transform().affine_inverse() * event.global_position

You should rather use inside _input:

  • var transformed_position = get_viewport().get_canvas_transform().affine_inverse() * event.position

Thanks a lot! Works like charm!