inputevent.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. .. _doc_inputevent:
  2. InputEvent
  3. ==========
  4. What is it?
  5. -----------
  6. Managing input is usually complex, no matter the OS or platform. To ease
  7. this a little, a special built-in type is provided, :ref:`InputEvent <class_InputEvent>`.
  8. This datatype can be configured to contain several types of input
  9. events. Input events travel through the engine and can be received in
  10. multiple locations, depending on the purpose.
  11. Here is a quick example, closing your game if the escape key is hit:
  12. .. tabs::
  13. .. code-tab:: gdscript GDScript
  14. func _unhandled_input(event):
  15. if event is InputEventKey:
  16. if event.pressed and event.scancode == KEY_ESCAPE:
  17. get_tree().quit()
  18. .. code-tab:: csharp
  19. public override void _UnhandledInput(InputEvent @event)
  20. {
  21. if (@event is InputEventKey eventKey)
  22. if (eventKey.Pressed && eventKey.Scancode == (int)KeyList.Escape)
  23. GetTree().Quit();
  24. }
  25. However, it is cleaner and more flexible to use the provided :ref:`InputMap <class_InputMap>` feature,
  26. which allows you to define input actions and assign them different keys. This way,
  27. you can define multiple keys for the same action (e.g. they keyboard escape key and the start button on a gamepad).
  28. You can then more easily change this mapping in the project settings without updating your code,
  29. and even build a key mapping feature on top of it to allow your game to change the key mapping at runtime!
  30. You can setup your InputMap under **Project > Project Settings > Input Map** and then use those actions like this:
  31. .. tabs::
  32. .. code-tab:: gdscript GDScript
  33. func _process(delta):
  34. if Input.is_action_pressed("ui_right"):
  35. # Move right
  36. .. code-tab:: csharp
  37. public override void _Process(float delta)
  38. {
  39. if (Input.IsActionPressed("ui_right"))
  40. {
  41. // Move right
  42. }
  43. }
  44. How does it work?
  45. -----------------
  46. Every input event is originated from the user/player (though it's
  47. possible to generate an InputEvent and feed them back to the engine,
  48. which is useful for gestures). The OS object for each platform will read
  49. events from the device, then feed them to MainLoop. As :ref:`SceneTree <class_SceneTree>`
  50. is the default MainLoop implementation, events are fed to it. Godot
  51. provides a function to get the current SceneTree object :
  52. **get_tree()**.
  53. But SceneTree does not know what to do with the event, so it will give
  54. it to the viewports, starting by the "root" :ref:`Viewport <class_Viewport>` (the first
  55. node of the scene tree). Viewport does quite a lot of stuff with the
  56. received input, in order:
  57. .. image:: img/input_event_flow.png
  58. 1. First of all, the standard :ref:`Node._input() <class_Node__input>`) function
  59. will be called in any node that overrides it (and hasn't disabled input processing with :ref:`Node.set_process_input() <class_Node_set_process_input>`).
  60. If any function consumes the event, it can call :ref:`SceneTree.set_input_as_handled() <class_SceneTree_set_input_as_handled>`, and the event will
  61. not spread any more. This ensures that you can filter all events of interest, even before the GUI.
  62. For gameplay input, :ref:`Node._unhandled_input() <class_Node__unhandled_input>`) is generally a better fit, because it allows the GUI to intercept the events.
  63. 2. Second, it will try to feed the input to the GUI, and see if any
  64. control can receive it. If so, the :ref:`Control <class_Control>` will be called via the
  65. virtual function :ref:`Control._gui_input() <class_Control__gui_input>` and the signal
  66. "input_event" will be emitted (this function is re-implementable by
  67. script by inheriting from it). If the control wants to "consume" the
  68. event, it will call :ref:`Control.accept_event() <class_Control_accept_event>` and the event will
  69. not spread any more. Events that are not consumed will propagate **up**,
  70. to :ref:`Control <class_Control>`'s ancestors. Use :ref:`Control.mouse_filter <class_Control_mouse_filter>`
  71. property to control whether a :ref:`Control <class_Control>` is notified
  72. of mouse events via :ref:`Control._gui_input() <class_Control__gui_input>`
  73. callback, and whether these events are propagated further.
  74. 3. If so far no one consumed the event, the unhandled input callback
  75. will be called if overridden (and not disabled with
  76. :ref:`Node.set_process_unhandled_input() <class_Node_set_process_unhandled_input>`).
  77. If any function consumes the event, it can call :ref:`SceneTree.set_input_as_handled() <class_SceneTree_set_input_as_handled>`, and the
  78. event will not spread any more. The unhandled input callback is ideal for full-screen gameplay events, so they are not received when a GUI is active.
  79. 4. If no one wanted the event so far, and a :ref:`Camera <class_Camera>` is assigned
  80. to the Viewport, a ray to the physics world (in the ray direction from
  81. the click) will be cast. If this ray hits an object, it will call the
  82. :ref:`CollisionObject._input_event() <class_CollisionObject__input_event>` function in the relevant
  83. physics object (bodies receive this callback by default, but areas do
  84. not. This can be configured through :ref:`Area <class_Area>` properties).
  85. 5. Finally, if the event was unhandled, it will be passed to the next
  86. Viewport in the tree, otherwise it will be ignored.
  87. Anatomy of an InputEvent
  88. ------------------------
  89. :ref:`InputEvent <class_InputEvent>` is just a base built-in type, it does not represent
  90. anything and only contains some basic information, such as event ID
  91. (which is increased for each event), device index, etc.
  92. There are several specialised types of InputEvent, described in the table below:
  93. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  94. | Event | Type Index | Description |
  95. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  96. | :ref:`InputEvent <class_InputEvent>` | NONE | Empty Input Event. |
  97. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  98. | :ref:`InputEventKey <class_InputEventKey>` | KEY | Contains a scancode and unicode value, |
  99. | | | as well as modifiers. |
  100. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  101. | :ref:`InputEventMouseButton <class_InputEventMouseButton>` | MOUSE_BUTTON | Contains click information, such as |
  102. | | | button, modifiers, etc. |
  103. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  104. | :ref:`InputEventMouseMotion <class_InputEventMouseMotion>` | MOUSE_MOTION | Contains motion information, such as |
  105. | | | relative, absolute positions and speed. |
  106. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  107. | :ref:`InputEventJoypadMotion <class_InputEventJoypadMotion>` | JOYSTICK_MOTION | Contains Joystick/Joypad analog axis |
  108. | | | information. |
  109. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  110. | :ref:`InputEventJoypadButton <class_InputEventJoypadButton>` | JOYSTICK_BUTTON | Contains Joystick/Joypad button |
  111. | | | information. |
  112. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  113. | :ref:`InputEventScreenTouch <class_InputEventScreenTouch>` | SCREEN_TOUCH | Contains multi-touch press/release |
  114. | | | information. (only available on mobile |
  115. | | | devices) |
  116. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  117. | :ref:`InputEventScreenDrag <class_InputEventScreenDrag>` | SCREEN_DRAG | Contains multi-touch drag information. |
  118. | | | (only available on mobile devices) |
  119. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  120. | :ref:`InputEventAction <class_InputEventAction>` | SCREEN_ACTION | Contains a generic action. These events |
  121. | | | are often generated by the programmer |
  122. | | | as feedback. (more on this below) |
  123. +-------------------------------------------------------------------+--------------------+-----------------------------------------+
  124. Actions
  125. -------
  126. An InputEvent may or may not represent a pre-defined action. Actions are
  127. useful because they abstract the input device when programming the game
  128. logic. This allows for:
  129. - The same code to work on different devices with different inputs (e.g.,
  130. keyboard on PC, Joypad on console).
  131. - Input to be reconfigured at run-time.
  132. Actions can be created from the Project Settings menu in the Actions
  133. tab.
  134. Any event has the methods :ref:`InputEvent.is_action() <class_InputEvent_is_action>`,
  135. :ref:`InputEvent.is_pressed() <class_InputEvent_is_pressed>` and :ref:`InputEvent <class_InputEvent>`.
  136. Alternatively, it may be desired to supply the game back with an action
  137. from the game code (a good example of this is detecting gestures).
  138. The Input singleton has a method for this:
  139. :ref:`Input.parse_input_event() <class_input_parse_input_event>`. You would normally use it like this:
  140. .. tabs::
  141. .. code-tab:: gdscript GDScript
  142. var ev = InputEventAction.new()
  143. # set as move_left, pressed
  144. ev.set_as_action("move_left", true)
  145. # feedback
  146. Input.parse_input_event(ev)
  147. .. code-tab:: csharp
  148. var ev = new InputEventAction();
  149. // set as move_left, pressed
  150. ev.SetAction("move_left");
  151. ev.SetPressed(true);
  152. // feedback
  153. Input.ParseInputEvent(ev);
  154. InputMap
  155. --------
  156. Customizing and re-mapping input from code is often desired. If your
  157. whole workflow depends on actions, the :ref:`InputMap <class_InputMap>` singleton is
  158. ideal for reassigning or creating different actions at run-time. This
  159. singleton is not saved (must be modified manually) and its state is run
  160. from the project settings (project.godot). So any dynamic system of this
  161. type needs to store settings in the way the programmer best sees fit.