浏览代码

Update Input Event Tutorial

Markus Sauermann 2 年之前
父节点
当前提交
d2a75723da
共有 2 个文件被更改,包括 48 次插入17 次删除
  1. 44 13
      tutorials/inputs/inputevent.rst
  2. 4 4
      tutorials/rendering/viewports.rst

+ 44 - 13
tutorials/inputs/inputevent.rst

@@ -69,12 +69,17 @@ received input, in order:
 
 
 .. image:: img/input_event_flow.png
 .. image:: img/input_event_flow.png
 
 
-1. First of all, the standard :ref:`Node._input() <class_Node_method__input>` function
+1. If the Viewport is embedding Windows, the Viewport tries to interpret the event in its
+   capability as a Window-Manager (e.g. for resizing or moving Windows).
+2. Next if an embedded Window is focused, the event is sent to that Window and processed in
+   the Windows Viewport. If no embedded Window is focused, The Event is sent to the nodes of
+   the current viewport in the following order.
+3. First of all, the standard :ref:`Node._input() <class_Node_method__input>` function
    will be called in any node that overrides it (and hasn't disabled input processing with :ref:`Node.set_process_input() <class_Node_method_set_process_input>`).
    will be called in any node that overrides it (and hasn't disabled input processing with :ref:`Node.set_process_input() <class_Node_method_set_process_input>`).
    If any function consumes the event, it can call :ref:`Viewport.set_input_as_handled() <class_Viewport_method_set_input_as_handled>`, and the event will
    If any function consumes the event, it can call :ref:`Viewport.set_input_as_handled() <class_Viewport_method_set_input_as_handled>`, and the event will
    not spread any more. This ensures that you can filter all events of interest, even before the GUI.
    not spread any more. This ensures that you can filter all events of interest, even before the GUI.
    For gameplay input, :ref:`Node._unhandled_input() <class_Node_method__unhandled_input>` is generally a better fit, because it allows the GUI to intercept the events.
    For gameplay input, :ref:`Node._unhandled_input() <class_Node_method__unhandled_input>` is generally a better fit, because it allows the GUI to intercept the events.
-2. Second, it will try to feed the input to the GUI, and see if any
+4. Second, it will try to feed the input to the GUI, and see if any
    control can receive it. If so, the :ref:`Control <class_Control>` will be called via the
    control can receive it. If so, the :ref:`Control <class_Control>` will be called via the
    virtual function :ref:`Control._gui_input() <class_Control_method__gui_input>` and the signal
    virtual function :ref:`Control._gui_input() <class_Control_method__gui_input>` and the signal
    "gui_input" will be emitted (this function is re-implementable by
    "gui_input" will be emitted (this function is re-implementable by
@@ -84,26 +89,52 @@ received input, in order:
    property to control whether a :ref:`Control <class_Control>` is notified
    property to control whether a :ref:`Control <class_Control>` is notified
    of mouse events via :ref:`Control._gui_input() <class_Control_method__gui_input>`
    of mouse events via :ref:`Control._gui_input() <class_Control_method__gui_input>`
    callback, and whether these events are propagated further.
    callback, and whether these events are propagated further.
-3. If so far no one consumed the event, the unhandled input callback
+5. If so far no one consumed the event, the :ref:`Node._shortcut_input() <class_Node_method__shortcut_input>` callback
+   will be called if overridden (and not disabled with
+   :ref:`Node.set_process_shortcut_input() <class_Node_method_set_process_shortcut_input>`).
+   This happens only for :ref:`InputEventKey <class_InputEventKey>`,
+   :ref:`InputEventShortcut <class_InputEventShortcut>` and :ref:`InputEventJoypadButton <class_InputEventJoypadButton>`.
+   If any function consumes the event, it can call :ref:`Viewport.set_input_as_handled() <class_Viewport_method_set_input_as_handled>`, and the
+   event will not spread any more. The shortcut input callback is ideal for treating events that are intended as shortcuts.
+6. If so far no one consumed the event, the :ref:`Node._unhandled_input() <class_Node_method__unhandled_input>` callback
    will be called if overridden (and not disabled with
    will be called if overridden (and not disabled with
    :ref:`Node.set_process_unhandled_input() <class_Node_method_set_process_unhandled_input>`).
    :ref:`Node.set_process_unhandled_input() <class_Node_method_set_process_unhandled_input>`).
    If any function consumes the event, it can call :ref:`Viewport.set_input_as_handled() <class_Viewport_method_set_input_as_handled>`, and the
    If any function consumes the event, it can call :ref:`Viewport.set_input_as_handled() <class_Viewport_method_set_input_as_handled>`, and the
    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.
    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.
-4. If no one wanted the event so far, and a :ref:`Camera3D <class_Camera3D>` is assigned
-   to the Viewport with :ref:`Object Picking <class_viewport_property_physics_object_picking>` turned on, a ray to the physics world (in the ray direction from
-   the click) will be cast. (For the root viewport, this can also be enabled in :ref:`Project Settings <class_ProjectSettings_property_physics/common/enable_object_picking>`.) If this ray hits an object, it will call the
-   :ref:`CollisionObject._input_event() <class_CollisionObject3D_method__input_event>` function in the relevant
-   physics object (bodies receive this callback by default, but areas do
+7. If so far no one consumed the event, the :ref:`Node._unhandled_key_input() <class_Node_method__unhandled_key_input>` callback
+   will be called if overridden (and not disabled with
+   :ref:`Node.set_process_unhandled_key_input() <class_Node_method_set_process_unhandled_key_input>`).
+   This happens only if the event is a :ref:`InputEventKey <class_InputEventKey>`.
+   If any function consumes the event, it can call :ref:`Viewport.set_input_as_handled() <class_Viewport_method_set_input_as_handled>`, and the
+   event will not spread any more. The unhandled key input callback is ideal for key events.
+8. If no one wanted the event so far, and :ref:`Object Picking <class_viewport_property_physics_object_picking>`
+   is turned on, the event is used for object picking. For the root viewport, this can also be
+   enabled in :ref:`Project Settings <class_ProjectSettings_property_physics/common/enable_object_picking>`.
+   In the case of a 3D scene if a :ref:`Camera3D <class_Camera3D>` is assigned to the Viewport, a ray
+   to the physics world (in the ray direction from the click) will be cast. If this ray hits an object,
+   it will call the :ref:`CollisionObject3D._input_event() <class_CollisionObject3D_method__input_event>`
+   function in the relevant physics object (bodies receive this callback by default, but areas do
    not. This can be configured through :ref:`Area3D <class_Area3D>` properties).
    not. This can be configured through :ref:`Area3D <class_Area3D>` properties).
-5. Finally, if the event was unhandled, it will be passed to the next
-   Viewport in the tree, otherwise it will be ignored.
+   In the case of a 2D scene, conceptually the same happens with :ref:`CollisionObject2D._input_event() <class_CollisionObject2D_method__input_event>`.
 
 
-When sending events to all listening nodes within a scene, the viewport
-will do so in a reverse depth-first order: Starting with the node at
-the bottom of the scene tree, and ending at the root node:
+When sending events to its child and descencand nodes, the viewport will do so, as depicted in
+the following graphic, in a reverse depth-first order, starting with the node at the bottom of
+the scene tree, and ending at the root node. Excluded from this process are embedded Windows
+and SubViewports.
 
 
 .. image:: img/input_event_scene_flow.png
 .. image:: img/input_event_scene_flow.png
 
 
+This order doesn't apply to :ref:`Control._gui_input() <class_Control_method__gui_input>`, which uses
+a different method based on event location or focused Control.
+
+Since Viewports don't send events to other :ref:`SubViewports <class_SubViewport>`, one of the following
+methods has to be used:
+
+1. Use a :ref:`SubViewportContainer <class_SubViewportContainer>`, which automatically
+   sends events to its child :ref:`SubViewports <class_SubViewport>` during
+   :ref:`Node._input() <class_Node_method__input>` and :ref:`Node._unhandled_input() <class_Node_method__unhandled_input>`.
+2. Implement event propagation based on the indivitual requirements.
+
 GUI events also travel up the scene tree but, since these events target
 GUI events also travel up the scene tree but, since these events target
 specific Controls, only direct ancestors of the targeted Control node receive the event.
 specific Controls, only direct ancestors of the targeted Control node receive the event.
 
 

+ 4 - 4
tutorials/rendering/viewports.rst

@@ -38,10 +38,10 @@ Input
 -----
 -----
 
 
 :ref:`Viewports <class_Viewport>` are also responsible for delivering properly adjusted and
 :ref:`Viewports <class_Viewport>` are also responsible for delivering properly adjusted and
-scaled input events to all their children nodes. Typically, input is received by the
-nearest :ref:`Viewport <class_Viewport>` in the tree, but you can set :ref:`Viewports <class_Viewport>` not to receive input by checking
-'Disable Input' to 'on'; this will allow the next nearest :ref:`Viewport <class_Viewport>` in the tree to capture
-the input.
+scaled input events to their children nodes. By default :ref:`SubViewports <class_SubViewport>` don't
+automatically receive input, unless they receive it from their direct
+:ref:`SubViewportContainer <class_SubViewportContainer>` parent node. In this case, input can be
+disabled with the :ref:`Disable Input <class_Viewport_property_gui_disable_input>` property.
 
 
 .. image:: img/input.png
 .. image:: img/input.png