2d_transforms.rst 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. .. _doc_viewport_and_canvas_transforms:
  2. Viewport and canvas transforms
  3. ==============================
  4. Introduction
  5. ------------
  6. This is an overview of the 2D transforms going on for nodes from the
  7. moment they draw their content locally to the time they are drawn onto
  8. the screen. This overview discusses very low-level details of the engine.
  9. The goal of this tutorial is to teach a way for feeding input events to the
  10. Input with a position in the correct coordinate system.
  11. A more extensive description of all coordinate systems and 2d transforms is
  12. available in :ref:`doc_2d_coordinate_systems`.
  13. Canvas transform
  14. ----------------
  15. As mentioned in the previous tutorial, :ref:`doc_canvas_layers`, every
  16. CanvasItem node (remember that Node2D and Control based nodes use
  17. CanvasItem as their common root) will reside in a *Canvas Layer*. Every
  18. canvas layer has a transform (translation, rotation, scale, etc.) that
  19. can be accessed as a :ref:`Transform2D <class_Transform2D>`.
  20. Also covered in the previous tutorial, nodes are drawn by default in Layer 0,
  21. in the built-in canvas. To put nodes in a different layer, a :ref:`CanvasLayer
  22. <class_CanvasLayer>` node can be used.
  23. Global canvas transform
  24. -----------------------
  25. Viewports also have a Global Canvas transform (also a
  26. :ref:`Transform2D <class_Transform2D>`). This is the master transform and
  27. affects all individual *Canvas Layer* transforms. Generally, this is primarily
  28. used in Godot's CanvasItem Editor.
  29. Stretch transform
  30. -----------------
  31. Finally, viewports have a *Stretch Transform*, which is used when
  32. resizing or stretching the screen. This transform is used internally (as
  33. described in :ref:`doc_multiple_resolutions`), but can also be manually set
  34. on each viewport.
  35. Input events are multiplied by this transform, but lack the ones above. To
  36. convert InputEvent coordinates to local CanvasItem coordinates, the
  37. :ref:`CanvasItem.make_input_local() <class_CanvasItem_method_make_input_local>`
  38. function was added for convenience.
  39. Window transform
  40. ----------------
  41. The root viewport is a :ref:`Window <class_Window>`. In order to scale and
  42. position the *Window's* content as described in :ref:`doc_multiple_resolutions`,
  43. each :ref:`Window <class_Window>` contains a *window transform*. It is for
  44. example responsible for the black bars at the *Window's* sides so that the
  45. *Viewport* is displayed with a fixed aspect ratio.
  46. Transform order
  47. ---------------
  48. To convert a CanvasItem local coordinate to an actual screen coordinate,
  49. the following chain of transforms must be applied:
  50. .. image:: img/viewport_transforms3.webp
  51. Transform functions
  52. -------------------
  53. The above graphic shows some available transform functions. All transforms are directed from right
  54. to left, this means multiplying a transform with a coordinate results in a coordinate system
  55. further to the left, multiplying the :ref:`affine inverse <class_Transform2D_method_affine_inverse>`
  56. of a transform results in a coordinate system further to the right:
  57. .. tabs::
  58. .. code-tab:: gdscript GDScript
  59. # Called from a CanvasItem.
  60. canvas_pos = get_global_transform() * local_pos
  61. local_pos = get_global_transform().affine_inverse() * canvas_pos
  62. .. code-tab:: csharp
  63. // Called from a CanvasItem.
  64. canvasPos = GetGlobalTransform() * localPos;
  65. localPos = GetGlobalTransform().AffineInverse() * canvasPos;
  66. Finally, then, to convert a CanvasItem local coordinates to screen coordinates, just multiply in
  67. the following order:
  68. .. tabs::
  69. .. code-tab:: gdscript GDScript
  70. var screen_coord = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos
  71. .. code-tab:: csharp
  72. var screenCoord = GetViewport().GetScreenTransform() * GetGlobalTransformWithCanvas() * localPos;
  73. Keep in mind, however, that it is generally not desired to work with screen coordinates. The
  74. recommended approach is to simply work in Canvas coordinates
  75. (``CanvasItem.get_global_transform()``), to allow automatic screen resolution resizing to work
  76. properly.
  77. Feeding custom input events
  78. ---------------------------
  79. It is often desired to feed custom input events to the game. With the above knowledge, to correctly
  80. do this in the focused window, it must be done the following way:
  81. .. tabs::
  82. .. code-tab:: gdscript GDScript
  83. var local_pos = Vector2(10, 20) # Local to Control/Node2D.
  84. var ie = InputEventMouseButton.new()
  85. ie.button_index = MOUSE_BUTTON_LEFT
  86. ie.position = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos
  87. Input.parse_input_event(ie)
  88. .. code-tab:: csharp
  89. var localPos = new Vector2(10,20); // Local to Control/Node2D.
  90. var ie = new InputEventMouseButton()
  91. {
  92. ButtonIndex = MouseButton.Left,
  93. Position = GetViewport().GetScreenTransform() * GetGlobalTransformWithCanvas() * localPos,
  94. };
  95. Input.ParseInputEvent(ie);