How can I make a Control node not recieve keyboard input?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By vivavovuve

I have two separate Control nodes that function as two separate UI elements (of which the child nodes are a viewport to the 3D worldspace and a TextEdit node, respectively), both of which respond to keyboard inputs, some of which overlap (the arrow keys for now, but later on this will be the case for hotkeys as well).

Currently, both Control nodes react to inputs (the left arrow key will move both the 3D character and the caret in the TextEdit node, for example). I’d like to disable keypress detection on one of them at a time, with the ability to switch between the two with a toggle key. I’ve experimented with grab_focus() as well as get_tree().paused = true and messing with pause modes, but no dice.

Any hints as to how I should go about this? I apologise in advance if I’ve overlooked something obvious.

:bust_in_silhouette: Reply From: DamonR

Hi,

You could try using a variable in an autoload script to keep track of which node you want active, and then set each nodes func _input() to only be active if that global variable says the node is active.

For example (quick pseudo code as on my phone);
If toggle_node is a button such as escape key.
In the autoload script (called Global.gd here);

var active_node = "3d"
func _input(event):
   if Input.is_action_just_pressed("toggle_node")
      if active_node == "3d":
         active_node = "text"
      elif active_node == "text":
         active_node = "3d"

In 3d world node;

func _input(event):
   if Global.active_node == "3d":
      Normal controls for this node
   else:
      pass

In text editor node;

func _input(event):
   if Global.active_node == "text":
      Normal controls for this node
   else:
      pass

That’s one way I can think of to control active bodes, but I have little experience with trying to achieve a setup such as yours, mine is mainly used for setting up menus and some UI elements.

Hope this helps.

Thanks! This solution would work as well (I assume), but the above solution seems cleaner and more flexible in the event that I want to add more elements to toggle between.

vivavovuve | 2019-08-16 14:23

Glad you found something that works. There are usually multiple ways to solve something. When I read the above solution I realised that it is what I used to prevent some nodes running code while another is meant to be as well.

DamonR | 2019-08-16 18:05

:bust_in_silhouette: Reply From: bad_exception

There is something like
set_processing( bool )
There are a couple of methods that turn on or off various proceesings in node.
One of them is responsible for managing input. Search documentation.

Thank you! Using set_processing_input( bool ) worked.
Posting the working code for posterity:

#When this is true, the focus is on the TextInput node (should start out at false):
var focus_input = false

#Path to node with the script that accepts input for player movement:
onready var player_script = $[Path]

#Path to TextEdit node:
onready var textedit = $[Path]

#Toggle between player movement and TextEdit node with "ui_toggle":
func _input(event):
if Input.is_action_pressed("ui_toggle"):
	focus_input = not focus_input
	if focus_input:
		player_script.set_process_input(false)
		textedit.set_process_input(true)
		textedit.grab_focus()
		textedit.set_editable(true)
	elif not focus_input:
		player_script.set_process_input(true)
		textedit.clear()
		textedit.set_editable(false)
		textedit.set_process_input(false)

vivavovuve | 2019-08-16 14:17