Skip to content

Commit 8111c91

Browse files
committed
Update 2D transform tutorial
Update "Viewport and canvas transforms" tutorial - incldue missing Window-transform - Update graphic to make the distinction between coordinate systems and transforms mode clear - Restructure "transform functions" section - Update functions to new Godot 4 conventions Create a more detailed page in engine documentation about 2d coordinate systems and 2d transforms.
1 parent 3c2412d commit 8111c91

File tree

6 files changed

+198
-35
lines changed

6 files changed

+198
-35
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
.. _doc_2d_coordinate_systems:
2+
3+
2D coordinate systems and 2D transforms
4+
=======================================
5+
6+
Introduction
7+
------------
8+
9+
This is a detailed overview of the available 2D coordinate systems and 2D transforms that are
10+
built in. The basic concepts are covered in :ref:`doc_viewport_and_canvas_transforms`.
11+
12+
:ref:`Transform2D <class_Transform2D>` are matrices that convert coordinates from one coordinate
13+
system to an other. In order to use them, it is beneficial to know which coordinate systems are
14+
available in Godot. For a deeper understanding, the :ref:`doc_matrices_and_transforms` tutorial
15+
offers insights to the underlying functionality.
16+
17+
Godot 2D coordinate systems
18+
---------------------------
19+
20+
The following graphic gives an overview of Godot 2D coordinate systems and the available
21+
node-transforms, transform-functions and coordinate-system related functions. At the left
22+
is the OS Window Manager screen, at the right are the :ref:`CanvasItems <class_CanvasItem>`. For
23+
simplicity reasons this graphic doesn't include :ref:`SubViewport <class_SubViewport>`,
24+
:ref:`SubViewportContainer <class_SubViewportContainer>`, :ref:`ParallaxLayer<class_ParallaxLayer>`
25+
and :ref:`ParallaxBackground<class_ParallaxBackground>` all of which also influence transforms.
26+
27+
The graphic is based on a node tree of the following form: ``Root Window (embed Windows)`` ⇒
28+
``Window (don't embed Windows)`` ⇒ ``CanvasLayer`` ⇒ ``CanvasItem`` ⇒ ``CanvasItem`` ⇒
29+
``CanvasItem``. There are more complex combinations possible, like deeply nested Window and
30+
SubViewports, however this example intends to provide an overview of the methodology in general.
31+
32+
.. image:: img/transforms_overview.webp
33+
:target: ../../../_images/transforms_overview.webp
34+
35+
Click graphic to enlarge.
36+
37+
- **Item Coordinates**
38+
This is the local coordinate system of a :ref:`CanvasItem <class_CanvasItem>`.
39+
40+
- **Parent Item Coordinates**
41+
This is the local coordinate system of the parent's *CanvasItem*. When positioning
42+
*CanvasItems* in the *Canvas*, they usually inherit the transformations of their parent
43+
*CanvasItems*. An exceptions is
44+
:ref:`CanvasItems.top_level <class_CanvasItem_property_top_level>`.
45+
46+
- **Canvas Coordinates**
47+
As mentioned in the previous tutorial :ref:`doc_canvas_layers`, there are two types of canvases
48+
(*Viewport* canvas and *CanvasLayer* canvas) and both have a canvas coordinate system. These
49+
are also called world coordinates. A *Viewport* can contain multiple *Canvases* with different
50+
coordinate systems.
51+
52+
- **Viewport Coordinates**
53+
This is the coordinate system of the :ref:`Viewport <class_Viewport>`.
54+
55+
- **Camera Coordinates**
56+
This is only used internally for functionality like 3D-camera ray projections.
57+
58+
- **Embedder Coordinates / Screen Coordinates**
59+
Every *Viewport* (*Window* or *SubViewport*) in the scene tree is embedded either in a
60+
different node or in the OS Window Manager. This coordinate system's origin is identical to the
61+
top-left corner of the *Window* or *SubViewport* and its scale is the one of the embedder or
62+
the OS Window Manager.
63+
64+
If the embedder is the OS Window Manager, then they are also called Screen Coordinates.
65+
66+
- **Absolute Embedder Coordinates / Absolute Screen Coordinates**
67+
The origin of this coordinate system is the top-left corner of the embedding node or the OS
68+
Window Manager screen. Its scale is the one of the embedder or the OS Window Manager.
69+
70+
If the embedder is the OS Window Manager, then they are also called Absolute Screen
71+
Coordinates.
72+
73+
74+
Node transforms
75+
---------------
76+
77+
Each of the mentioned nodes have one or more transforms associated with them and the combination of
78+
these nodes infer the transforms between the different coordinate systems. With a few exceptions,
79+
the transforms are :ref:`Transform2D <class_Transform2D>` and the following list shows details and
80+
effects of each of them.
81+
82+
- **CanvasItem transform**
83+
*CanvasItems* are either *Control*-nodes or *Node2D*-nodes.
84+
85+
For *Control* nodes this transform consists of a :ref:`position <class_Control_property_position>`
86+
relative to the parent's origin and a :ref:`scale <class_Control_property_scale>` and
87+
:ref:`rotation <class_Control_property_rotation>` around a
88+
:ref:`pivot point <class_Control_property_pivot_offset>`.
89+
90+
For *Node2D* nodes :ref:`transform <class_Node2D_property_transform>` consists of
91+
:ref:`position <class_Node2D_property_position>`, :ref:`rotation <class_Node2D_property_rotation>`,
92+
:ref:`scale <class_Node2D_property_scale>` and :ref:`skew <class_Node2D_property_skew>`.
93+
94+
The transform affects the item itself and usually also child-*CanvasItems* and in the case of a
95+
*SubViewportContainer* it affects the contained *SubViewport*.
96+
97+
- **CanvasLayer transform**
98+
The *CanvasLayer's* :ref:`transform <class_CanvasLayer_property_transform>` affects all
99+
*CanvasItems* within the *CanvasLayer*. It doesn't affect other *CanvasLayers* or *Windows* in
100+
its *Viewport*.
101+
102+
- **CanvasLayer follow viewport transform**
103+
The *follow viewport transform* is an automatically calculated transform, that is based on the
104+
*Viewport's* :ref:`canvas transform <class_Viewport_property_canvas_transform>` and the
105+
*CanvasLayer's* :ref:`follow viewport scale <class_CanvasLayer_property_follow_viewport_scale>`
106+
and can be used, if :ref:`enabled <class_CanvasLayer_property_follow_viewport_enabled>`, to
107+
achieve a pseudo 3D effect. It affects the same child nodes as the *CanvasLayer transform*.
108+
109+
- **Viewport canvas transform**
110+
The :ref:`canvas transform <class_Viewport_property_canvas_transform>` affects all
111+
*CanvasItems* in the *Viewport's* default canvas. It also affects *CanvasLayers*, that have
112+
follow viewport transform enabled. The *Viewport's* active :ref:`Camera2D <class_Camera2D>`
113+
works by changing this transform. It doesn't affect this *Viewport's* embedded *Windows*.
114+
115+
- **Viewport global canvas transform**
116+
*Viewports* also have a :ref:`global canvas transform <class_Viewport_property_global_canvas_transform>`.
117+
This is the master transform and affects all individual *Canvas Layer* and embedded *Window*
118+
transforms. This is primarily used in Godot's CanvasItem Editor.
119+
120+
- **Viewport stretch transform**
121+
Finally, *Viewports* have a *stretch transform*, which is used when resizing or stretching the
122+
viewport. This transform is used for :ref:`Windows <class_Window>` as described in
123+
:ref:`doc_multiple_resolutions`, but can also be manually set on *SubViewports* by means of
124+
:ref:`size <class_SubViewport_property_size>` and
125+
:ref:`size_2d_override <class_SubViewport_property_size_2d_override>`. It's
126+
:ref:`translation <class_Transform2D_method_get_origin>`,
127+
:ref:`rotation <class_Transform2D_method_get_rotation>` and
128+
:ref:`skew <class_Transform2D_method_get_skew>` are the default values and it can only have
129+
non-default :ref:`scale <class_Transform2D_method_get_scale>`.
130+
131+
- **Window transform**
132+
In order to scale and position the *Window's* content as described in
133+
:ref:`doc_multiple_resolutions`, each :ref:`Window <class_Window>` contains a
134+
*window transform*. It is for example responsible for the black bars at the *Window's* sides so
135+
that the *Viewport* is displayed with a fixed aspect ratio.
136+
137+
- **Window position**
138+
Every *Window* also has a :ref:`position <class_Window_property_position>` to describe its
139+
position within its embedder. The embedder can be another *Viewport* or the OS Window Manager.
140+
141+
- **SubViewportContainer shrink transform**
142+
:ref:`stretch <class_SubViewportContainer_property_stretch>` together with
143+
:ref:`stretch_shrink <class_SubViewportContainer_property_stretch_shrink>` declare for a
144+
*SubViewportContaner* if and by what integer factor the contained *SubViewport* should be
145+
scaled in comparison to the container's size.
67.8 KB
Loading

contributing/development/core_and_modules/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ This section covers the basics that you will encounter in (almost) every source
2020
object_class
2121
inheritance_class_tree
2222
internal_rendering_architecture
23+
2d_coordinate_systems
2324

2425
Extending Godot by modifying its source code
2526
--------------------------------------------

tutorials/2d/2d_transforms.rst

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
:article_outdated: True
2-
31
.. _doc_viewport_and_canvas_transforms:
42

53
Viewport and canvas transforms
@@ -12,6 +10,12 @@ This is an overview of the 2D transforms going on for nodes from the
1210
moment they draw their content locally to the time they are drawn onto
1311
the screen. This overview discusses very low level details of the engine.
1412

13+
The goal of this tutorial is to teach a way for feeding input events to the
14+
Input with a position in the correct coordinate system.
15+
16+
A more extensive description of all coordinate systems and 2d transforms is
17+
available in :ref:`doc_2d_coordinate_systems`.
18+
1519
Canvas transform
1620
----------------
1721

@@ -30,9 +34,8 @@ Global canvas transform
3034

3135
Viewports also have a Global Canvas transform (also a
3236
:ref:`Transform2D <class_Transform2D>`). This is the master transform and
33-
affects all individual *Canvas Layer* transforms. Generally, this
34-
transform is not of much use, but is used in the CanvasItem Editor
35-
in Godot's editor.
37+
affects all individual *Canvas Layer* transforms. Generally, this is primarily
38+
used in Godot's CanvasItem Editor.
3639

3740
Stretch transform
3841
-----------------
@@ -47,68 +50,82 @@ convert InputEvent coordinates to local CanvasItem coordinates, the
4750
:ref:`CanvasItem.make_input_local() <class_CanvasItem_method_make_input_local>`
4851
function was added for convenience.
4952

53+
Window transform
54+
----------------
55+
56+
The root viewport is a :ref:`Window <class_Window>`. In order to scale and
57+
position the *Window's* content as described in :ref:`doc_multiple_resolutions`,
58+
each :ref:`Window <class_Window>` contains a *window transform*. It is for
59+
example responsible for the black bars at the *Window's* sides so that the
60+
*Viewport* is displayed with a fixed aspect ratio.
61+
5062
Transform order
5163
---------------
5264

53-
For a coordinate in CanvasItem local properties to become an actual
54-
screen coordinate, the following chain of transforms must be applied:
65+
To convert a CanvasItem local coordinate to an actual screen coordinate,
66+
the following chain of transforms must be applied:
5567

56-
.. image:: img/viewport_transforms2.png
68+
.. image:: img/viewport_transforms3.webp
5769

5870
Transform functions
5971
-------------------
6072

61-
Obtaining each transform can be achieved with the following functions:
73+
The above graphic shows some available transform functions. All transforms are directed from right
74+
to left, this means multiplying a transform with a coordinate results in a coordinate system
75+
further to the left, multiplying the :ref:`affine inverse <class_Transform2D_method_affine_inverse>`
76+
of a transform results in a coordinate system further to the right:
77+
78+
.. tabs::
79+
.. code-tab:: gdscript GDScript
80+
81+
# Called from a CanvasItem.
82+
canvas_pos = get_global_transform() * local_pos
83+
local_pos = get_global_transform().affine_inverse() * canvas_pos
84+
85+
.. code-tab:: csharp
6286

63-
+----------------------------------+---------------------------------------------------------------------------------------------+
64-
| Type | Transform |
65-
+==================================+=============================================================================================+
66-
| CanvasItem | :ref:`CanvasItem.get_global_transform() <class_CanvasItem_method_get_global_transform>` |
67-
+----------------------------------+---------------------------------------------------------------------------------------------+
68-
| CanvasLayer | :ref:`CanvasItem.get_canvas_transform() <class_CanvasItem_method_get_canvas_transform>` |
69-
+----------------------------------+---------------------------------------------------------------------------------------------+
70-
| CanvasLayer+GlobalCanvas+Stretch | :ref:`CanvasItem.get_viewport_transform() <class_CanvasItem_method_get_viewport_transform>` |
71-
+----------------------------------+---------------------------------------------------------------------------------------------+
87+
// Called from a CanvasItem.
88+
canvasPos = GetGlobalTransform() * localPos;
89+
localPos = GetGlobalTransform().AffineInverse() * canvasPos;
7290

73-
Finally, then, to convert a CanvasItem local coordinates to screen
74-
coordinates, just multiply in the following order:
91+
Finally, then, to convert a CanvasItem local coordinates to screen coordinates, just multiply in
92+
the following order:
7593

7694
.. tabs::
7795
.. code-tab:: gdscript GDScript
7896

79-
var screen_coord = get_viewport_transform() * (get_global_transform() * local_pos)
97+
var screen_coord = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos
8098

8199
.. code-tab:: csharp
82100

83-
var screenCord = GetViewportTransform() * (GetGlobalTransform() * localPos);
101+
var screenCord = GetViewport().GetScreenTransform() * GetGlobalTransformWithCanvas() * localPos;
84102

85-
Keep in mind, however, that it is generally not desired to work with
86-
screen coordinates. The recommended approach is to simply work in Canvas
87-
coordinates (``CanvasItem.get_global_transform()``), to allow automatic
88-
screen resolution resizing to work properly.
103+
Keep in mind, however, that it is generally not desired to work with screen coordinates. The
104+
recommended approach is to simply work in Canvas coordinates
105+
(``CanvasItem.get_global_transform()``), to allow automatic screen resolution resizing to work
106+
properly.
89107

90108
Feeding custom input events
91109
---------------------------
92110

93-
It is often desired to feed custom input events to the scene tree. With
94-
the above knowledge, to correctly do this, it must be done the following
95-
way:
111+
It is often desired to feed custom input events to the game. With the above knowledge, to correctly
112+
do this in the focused window, it must be done the following way:
96113

97114
.. tabs::
98115
.. code-tab:: gdscript GDScript
99116

100-
var local_pos = Vector2(10, 20) # local to Control/Node2D
117+
var local_pos = Vector2(10, 20) # Local to Control/Node2D.
101118
var ie = InputEventMouseButton.new()
102119
ie.button_index = MOUSE_BUTTON_LEFT
103-
ie.position = get_viewport_transform() * (get_global_transform() * local_pos)
104-
get_tree().input_event(ie)
120+
ie.position = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos
121+
Input.parse_input_event(ie)
105122

106123
.. code-tab:: csharp
107124

108-
var localPos = new Vector2(10,20); // local to Control/Node2D
125+
var localPos = new Vector2(10,20); // Local to Control/Node2D.
109126
var ie = new InputEventMouseButton()
110127
{
111128
ButtonIndex = MouseButton.Left,
112-
Position = GetViewportTransform() * (GetGlobalTransform() * localPos),
129+
Position = GetViewport().GetScreenTransform() * GetGlobalTransformWithCanvas() * localPos,
113130
};
114-
GetTree().InputEvent(ie);
131+
Input.ParseInputEvent(ie);
-11 KB
Binary file not shown.
15.1 KB
Loading

0 commit comments

Comments
 (0)