One piece of that logic is to click on the node to select it and then have it follow the cursor to move it around. In general that is working but the problem is that when I move the cursor too fast, I am loosing the focus on the node and therefore it stops moving.
Is there a way to prevent this so that the input events are solely handled by that node until the user clicks the button again and it gets released?
Below my current script:
func _on_input_event(camera: Node, event: InputEvent, event_position: Vector3, normal: Vector3, shape_idx: int) -> void:
if event is InputEventMouseButton and event.is_pressed():
if event.button_index == MOUSE_BUTTON_LEFT:
Globals.skipMove = false
if Globals.selectedNode == self:
self.showCrossMarker(false)
Globals.selectedNode = null
else:
Globals.selectedNode = self
if event is InputEventMouse:
if !Globals.skipMove:
self.showCrossMarker(true)
var currentY = self.global_position.y
var pos = Vector3(event_position)
self.global_position = pos
self.global_position.y = currentY
I’d recommend checking out a 2D drag-and-drop tutorial. But the simple answer is to have an is_dragging variable, and when it is true, update the location of the object every frame in the _process() function.
The CollisionObject3D.input_event signal only works while event happens inside the object collision shapes, if the mouse exits the object then it won’t be registered.
You can use that signal to know when the object is clicked on but you’ll need to process the dragging in another place like Node._input() for example.
Thanks @dragonforge-dev - I have reshaped the functions and now it works like a charm and also looks way better
func _on_input_event(camera: Node, event: InputEvent, event_position: Vector3, normal: Vector3, shape_idx: int) -> void:
if event is InputEventMouseButton:
if event.is_pressed():
if event.button_index == MOUSE_BUTTON_LEFT:
Globals.skipMove = false
self.isDragging = true
self.showCrossMarker(true)
if event.button_index == MOUSE_BUTTON_RIGHT:
var object_of_interest_3D_position : Vector3 = self.global_position
var HUDposition = get_viewport().get_camera_3d().unproject_position( object_of_interest_3D_position )
var rect: Rect2i = Rect2i(HUDposition.x, HUDposition.y, 800, 800)
%PopupMenu.popup(rect)
if event.is_released():
if event.button_index == MOUSE_BUTTON_LEFT:
self.isDragging = false
self.showCrossMarker(false)
and
func _process(delta: float) -> void:
# Handle drag movement
if self.isDragging:
var camera = get_viewport().get_camera_3d()
if camera:
var mousePos = get_viewport().get_mouse_position()
# Create a ray from camera through mouse position
var rayOrigin = camera.project_ray_origin(mousePos)
var rayNormal = camera.project_ray_normal(mousePos)
# Calculate intersection with the plane at the node's Y level
var targetY = self.global_position.y
var t = (targetY - rayOrigin.y) / rayNormal.y if rayNormal.y != 0 else 0
var newPosition = rayOrigin + rayNormal * t
newPosition.y = targetY
var snapper = Vector3(0.5,0,0.5)
var snappedPos = newPosition.snapped(snapper)
if(!self.global_position.is_equal_approx(snappedPos)):
self.global_position = snappedPos
self.global_position.y = targetY