Godot Version
4.2.2
Question
Hi all,
I’d appreciate some help handling input with multiple viewports.
I have a split screen view created using two subviewports.
Each viewport renders a different scene and these scenes work independently as expected: the ‘player’ in each scene responds to the mouse “click” event by calling my pathfinding script to navigate the tilemap.
However, when I place these scenes in their respective subviewports, mouse input for the scene with the larger tile map is still being called when clicking on the other viewport. In other words, when a mouse click occurs on a tile that is walkable, the movement occurs, even if that tile wasn’t currently on screen.
I’ve tried using get_viewport().get_mouse_position()
rather than get_global_mouse_position()
. However, that doesn’t seem to report the mouse position only for that viewport.
I think i’m looking for a way to either:
- restrict mouse input to the viewport currently under the mouse
or
- toggle each viewport’s ability to receive mouse events on and off
I came across this forum post but despite looking at the viewport documentation, I’ve not been able to work out how to implement this.
My input code (a script on the ‘player’ in the world scene) currently looks like this:
func _physics_process(delta):
if Input.is_action_just_pressed("click"):
var mouse_pos = get_viewport().get_mouse_position()
var tile_pos = terrain.local_to_map(mouse_pos)
# get current position in tile space
var current_pos = terrain.local_to_map(position)
# get target postion by converting mouse to tile position
var target_pos = terrain.local_to_map(terrain.get_local_mouse_position())
path = pathfinding.find_path(current_pos, target_pos)
if len(path) > 0:
var direction = global_position.direction_to(path[0])
var terrain_difficulty = pathfinding.get_terrain_difficulty(terrain.local_to_map(position))
velocity = direction * SPEED * (1 / terrain_difficulty)
look_at(path[0])
if position.distance_to(path[0]) < SPEED * delta:
path.remove_at(0)
else:
velocity = Vector2.ZERO
move_and_slide()
My node hierarchy looks like this:
I think i’ve almost got there by using has_point()
on the viewport_rect()
to check is the mouse click event position is within it. However, i’m struggling to refactor my physics_process code to separate out the positioning code from the movement code, which needs delta
.
func _input(event):
if event is InputEventMouse and event.is_action_pressed("click"):
var container = get_viewport()
if get_viewport_rect().has_point(event.position):
print("within the world viewport") # <-- seems to only fire when clicks are within the viewport, as intended
var mouse_pos = event.position
print("mouse pos: ", mouse_pos)
I would be grateful for some help. Thank you.