mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-04 14:11:02 +03:00
Merge pull request #6277 from Sauermann/fix-transform-2d-update
This commit is contained in:
committed by
Max Hilbrunner
parent
ff8b08c16c
commit
35e18ba9ff
@@ -0,0 +1,145 @@
|
||||
.. _doc_2d_coordinate_systems:
|
||||
|
||||
2D coordinate systems and 2D transforms
|
||||
=======================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This is a detailed overview of the available 2D coordinate systems and 2D transforms that are
|
||||
built in. The basic concepts are covered in :ref:`doc_viewport_and_canvas_transforms`.
|
||||
|
||||
:ref:`Transform2D <class_Transform2D>` are matrices that convert coordinates from one coordinate
|
||||
system to an other. In order to use them, it is beneficial to know which coordinate systems are
|
||||
available in Godot. For a deeper understanding, the :ref:`doc_matrices_and_transforms` tutorial
|
||||
offers insights to the underlying functionality.
|
||||
|
||||
Godot 2D coordinate systems
|
||||
---------------------------
|
||||
|
||||
The following graphic gives an overview of Godot 2D coordinate systems and the available
|
||||
node-transforms, transform-functions and coordinate-system related functions. At the left
|
||||
is the OS Window Manager screen, at the right are the :ref:`CanvasItems <class_CanvasItem>`. For
|
||||
simplicity reasons this graphic doesn't include :ref:`SubViewport <class_SubViewport>`,
|
||||
:ref:`SubViewportContainer <class_SubViewportContainer>`, :ref:`ParallaxLayer<class_ParallaxLayer>`
|
||||
and :ref:`ParallaxBackground<class_ParallaxBackground>` all of which also influence transforms.
|
||||
|
||||
The graphic is based on a node tree of the following form: ``Root Window (embed Windows)`` ⇒
|
||||
``Window (don't embed Windows)`` ⇒ ``CanvasLayer`` ⇒ ``CanvasItem`` ⇒ ``CanvasItem`` ⇒
|
||||
``CanvasItem``. There are more complex combinations possible, like deeply nested Window and
|
||||
SubViewports, however this example intends to provide an overview of the methodology in general.
|
||||
|
||||
.. image:: img/transforms_overview.webp
|
||||
:target: ../../../_images/transforms_overview.webp
|
||||
|
||||
Click graphic to enlarge.
|
||||
|
||||
- **Item Coordinates**
|
||||
This is the local coordinate system of a :ref:`CanvasItem <class_CanvasItem>`.
|
||||
|
||||
- **Parent Item Coordinates**
|
||||
This is the local coordinate system of the parent's *CanvasItem*. When positioning
|
||||
*CanvasItems* in the *Canvas*, they usually inherit the transformations of their parent
|
||||
*CanvasItems*. An exceptions is
|
||||
:ref:`CanvasItems.top_level <class_CanvasItem_property_top_level>`.
|
||||
|
||||
- **Canvas Coordinates**
|
||||
As mentioned in the previous tutorial :ref:`doc_canvas_layers`, there are two types of canvases
|
||||
(*Viewport* canvas and *CanvasLayer* canvas) and both have a canvas coordinate system. These
|
||||
are also called world coordinates. A *Viewport* can contain multiple *Canvases* with different
|
||||
coordinate systems.
|
||||
|
||||
- **Viewport Coordinates**
|
||||
This is the coordinate system of the :ref:`Viewport <class_Viewport>`.
|
||||
|
||||
- **Camera Coordinates**
|
||||
This is only used internally for functionality like 3D-camera ray projections.
|
||||
|
||||
- **Embedder Coordinates / Screen Coordinates**
|
||||
Every *Viewport* (*Window* or *SubViewport*) in the scene tree is embedded either in a
|
||||
different node or in the OS Window Manager. This coordinate system's origin is identical to the
|
||||
top-left corner of the *Window* or *SubViewport* and its scale is the one of the embedder or
|
||||
the OS Window Manager.
|
||||
|
||||
If the embedder is the OS Window Manager, then they are also called Screen Coordinates.
|
||||
|
||||
- **Absolute Embedder Coordinates / Absolute Screen Coordinates**
|
||||
The origin of this coordinate system is the top-left corner of the embedding node or the OS
|
||||
Window Manager screen. Its scale is the one of the embedder or the OS Window Manager.
|
||||
|
||||
If the embedder is the OS Window Manager, then they are also called Absolute Screen
|
||||
Coordinates.
|
||||
|
||||
|
||||
Node transforms
|
||||
---------------
|
||||
|
||||
Each of the mentioned nodes have one or more transforms associated with them and the combination of
|
||||
these nodes infer the transforms between the different coordinate systems. With a few exceptions,
|
||||
the transforms are :ref:`Transform2D <class_Transform2D>` and the following list shows details and
|
||||
effects of each of them.
|
||||
|
||||
- **CanvasItem transform**
|
||||
*CanvasItems* are either *Control*-nodes or *Node2D*-nodes.
|
||||
|
||||
For *Control* nodes this transform consists of a :ref:`position <class_Control_property_position>`
|
||||
relative to the parent's origin and a :ref:`scale <class_Control_property_scale>` and
|
||||
:ref:`rotation <class_Control_property_rotation>` around a
|
||||
:ref:`pivot point <class_Control_property_pivot_offset>`.
|
||||
|
||||
For *Node2D* nodes :ref:`transform <class_Node2D_property_transform>` consists of
|
||||
:ref:`position <class_Node2D_property_position>`, :ref:`rotation <class_Node2D_property_rotation>`,
|
||||
:ref:`scale <class_Node2D_property_scale>` and :ref:`skew <class_Node2D_property_skew>`.
|
||||
|
||||
The transform affects the item itself and usually also child-*CanvasItems* and in the case of a
|
||||
*SubViewportContainer* it affects the contained *SubViewport*.
|
||||
|
||||
- **CanvasLayer transform**
|
||||
The *CanvasLayer's* :ref:`transform <class_CanvasLayer_property_transform>` affects all
|
||||
*CanvasItems* within the *CanvasLayer*. It doesn't affect other *CanvasLayers* or *Windows* in
|
||||
its *Viewport*.
|
||||
|
||||
- **CanvasLayer follow viewport transform**
|
||||
The *follow viewport transform* is an automatically calculated transform, that is based on the
|
||||
*Viewport's* :ref:`canvas transform <class_Viewport_property_canvas_transform>` and the
|
||||
*CanvasLayer's* :ref:`follow viewport scale <class_CanvasLayer_property_follow_viewport_scale>`
|
||||
and can be used, if :ref:`enabled <class_CanvasLayer_property_follow_viewport_enabled>`, to
|
||||
achieve a pseudo 3D effect. It affects the same child nodes as the *CanvasLayer transform*.
|
||||
|
||||
- **Viewport canvas transform**
|
||||
The :ref:`canvas transform <class_Viewport_property_canvas_transform>` affects all
|
||||
*CanvasItems* in the *Viewport's* default canvas. It also affects *CanvasLayers*, that have
|
||||
follow viewport transform enabled. The *Viewport's* active :ref:`Camera2D <class_Camera2D>`
|
||||
works by changing this transform. It doesn't affect this *Viewport's* embedded *Windows*.
|
||||
|
||||
- **Viewport global canvas transform**
|
||||
*Viewports* also have a :ref:`global canvas transform <class_Viewport_property_global_canvas_transform>`.
|
||||
This is the master transform and affects all individual *Canvas Layer* and embedded *Window*
|
||||
transforms. This is primarily used in Godot's CanvasItem Editor.
|
||||
|
||||
- **Viewport stretch transform**
|
||||
Finally, *Viewports* have a *stretch transform*, which is used when resizing or stretching the
|
||||
viewport. This transform is used for :ref:`Windows <class_Window>` as described in
|
||||
:ref:`doc_multiple_resolutions`, but can also be manually set on *SubViewports* by means of
|
||||
:ref:`size <class_SubViewport_property_size>` and
|
||||
:ref:`size_2d_override <class_SubViewport_property_size_2d_override>`. It's
|
||||
:ref:`translation <class_Transform2D_method_get_origin>`,
|
||||
:ref:`rotation <class_Transform2D_method_get_rotation>` and
|
||||
:ref:`skew <class_Transform2D_method_get_skew>` are the default values and it can only have
|
||||
non-default :ref:`scale <class_Transform2D_method_get_scale>`.
|
||||
|
||||
- **Window transform**
|
||||
In order to scale and position the *Window's* content as described in
|
||||
:ref:`doc_multiple_resolutions`, each :ref:`Window <class_Window>` contains a
|
||||
*window transform*. It is for example responsible for the black bars at the *Window's* sides so
|
||||
that the *Viewport* is displayed with a fixed aspect ratio.
|
||||
|
||||
- **Window position**
|
||||
Every *Window* also has a :ref:`position <class_Window_property_position>` to describe its
|
||||
position within its embedder. The embedder can be another *Viewport* or the OS Window Manager.
|
||||
|
||||
- **SubViewportContainer shrink transform**
|
||||
:ref:`stretch <class_SubViewportContainer_property_stretch>` together with
|
||||
:ref:`stretch_shrink <class_SubViewportContainer_property_stretch_shrink>` declare for a
|
||||
*SubViewportContaner* if and by what integer factor the contained *SubViewport* should be
|
||||
scaled in comparison to the container's size.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
@@ -20,6 +20,7 @@ This section covers the basics that you will encounter in (almost) every source
|
||||
object_class
|
||||
inheritance_class_tree
|
||||
internal_rendering_architecture
|
||||
2d_coordinate_systems
|
||||
|
||||
Extending Godot by modifying its source code
|
||||
--------------------------------------------
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
:article_outdated: True
|
||||
|
||||
.. _doc_viewport_and_canvas_transforms:
|
||||
|
||||
Viewport and canvas transforms
|
||||
@@ -12,6 +10,12 @@ This is an overview of the 2D transforms going on for nodes from the
|
||||
moment they draw their content locally to the time they are drawn onto
|
||||
the screen. This overview discusses very low level details of the engine.
|
||||
|
||||
The goal of this tutorial is to teach a way for feeding input events to the
|
||||
Input with a position in the correct coordinate system.
|
||||
|
||||
A more extensive description of all coordinate systems and 2d transforms is
|
||||
available in :ref:`doc_2d_coordinate_systems`.
|
||||
|
||||
Canvas transform
|
||||
----------------
|
||||
|
||||
@@ -30,9 +34,8 @@ Global canvas transform
|
||||
|
||||
Viewports also have a Global Canvas transform (also a
|
||||
:ref:`Transform2D <class_Transform2D>`). This is the master transform and
|
||||
affects all individual *Canvas Layer* transforms. Generally, this
|
||||
transform is not of much use, but is used in the CanvasItem Editor
|
||||
in Godot's editor.
|
||||
affects all individual *Canvas Layer* transforms. Generally, this is primarily
|
||||
used in Godot's CanvasItem Editor.
|
||||
|
||||
Stretch transform
|
||||
-----------------
|
||||
@@ -47,68 +50,82 @@ convert InputEvent coordinates to local CanvasItem coordinates, the
|
||||
:ref:`CanvasItem.make_input_local() <class_CanvasItem_method_make_input_local>`
|
||||
function was added for convenience.
|
||||
|
||||
Window transform
|
||||
----------------
|
||||
|
||||
The root viewport is a :ref:`Window <class_Window>`. In order to scale and
|
||||
position the *Window's* content as described in :ref:`doc_multiple_resolutions`,
|
||||
each :ref:`Window <class_Window>` contains a *window transform*. It is for
|
||||
example responsible for the black bars at the *Window's* sides so that the
|
||||
*Viewport* is displayed with a fixed aspect ratio.
|
||||
|
||||
Transform order
|
||||
---------------
|
||||
|
||||
For a coordinate in CanvasItem local properties to become an actual
|
||||
screen coordinate, the following chain of transforms must be applied:
|
||||
To convert a CanvasItem local coordinate to an actual screen coordinate,
|
||||
the following chain of transforms must be applied:
|
||||
|
||||
.. image:: img/viewport_transforms2.png
|
||||
.. image:: img/viewport_transforms3.webp
|
||||
|
||||
Transform functions
|
||||
-------------------
|
||||
|
||||
Obtaining each transform can be achieved with the following functions:
|
||||
|
||||
+----------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| Type | Transform |
|
||||
+==================================+=============================================================================================+
|
||||
| CanvasItem | :ref:`CanvasItem.get_global_transform() <class_CanvasItem_method_get_global_transform>` |
|
||||
+----------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| CanvasLayer | :ref:`CanvasItem.get_canvas_transform() <class_CanvasItem_method_get_canvas_transform>` |
|
||||
+----------------------------------+---------------------------------------------------------------------------------------------+
|
||||
| CanvasLayer+GlobalCanvas+Stretch | :ref:`CanvasItem.get_viewport_transform() <class_CanvasItem_method_get_viewport_transform>` |
|
||||
+----------------------------------+---------------------------------------------------------------------------------------------+
|
||||
|
||||
Finally, then, to convert a CanvasItem local coordinates to screen
|
||||
coordinates, just multiply in the following order:
|
||||
The above graphic shows some available transform functions. All transforms are directed from right
|
||||
to left, this means multiplying a transform with a coordinate results in a coordinate system
|
||||
further to the left, multiplying the :ref:`affine inverse <class_Transform2D_method_affine_inverse>`
|
||||
of a transform results in a coordinate system further to the right:
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
var screen_coord = get_viewport_transform() * (get_global_transform() * local_pos)
|
||||
# Called from a CanvasItem.
|
||||
canvas_pos = get_global_transform() * local_pos
|
||||
local_pos = get_global_transform().affine_inverse() * canvas_pos
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
var screenCord = GetViewportTransform() * (GetGlobalTransform() * localPos);
|
||||
// Called from a CanvasItem.
|
||||
canvasPos = GetGlobalTransform() * localPos;
|
||||
localPos = GetGlobalTransform().AffineInverse() * canvasPos;
|
||||
|
||||
Keep in mind, however, that it is generally not desired to work with
|
||||
screen coordinates. The recommended approach is to simply work in Canvas
|
||||
coordinates (``CanvasItem.get_global_transform()``), to allow automatic
|
||||
screen resolution resizing to work properly.
|
||||
Finally, then, to convert a CanvasItem local coordinates to screen coordinates, just multiply in
|
||||
the following order:
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
var screen_coord = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
var screenCord = GetViewport().GetScreenTransform() * GetGlobalTransformWithCanvas() * localPos;
|
||||
|
||||
Keep in mind, however, that it is generally not desired to work with screen coordinates. The
|
||||
recommended approach is to simply work in Canvas coordinates
|
||||
(``CanvasItem.get_global_transform()``), to allow automatic screen resolution resizing to work
|
||||
properly.
|
||||
|
||||
Feeding custom input events
|
||||
---------------------------
|
||||
|
||||
It is often desired to feed custom input events to the scene tree. With
|
||||
the above knowledge, to correctly do this, it must be done the following
|
||||
way:
|
||||
It is often desired to feed custom input events to the game. With the above knowledge, to correctly
|
||||
do this in the focused window, it must be done the following way:
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
var local_pos = Vector2(10, 20) # local to Control/Node2D
|
||||
var local_pos = Vector2(10, 20) # Local to Control/Node2D.
|
||||
var ie = InputEventMouseButton.new()
|
||||
ie.button_index = MOUSE_BUTTON_LEFT
|
||||
ie.position = get_viewport_transform() * (get_global_transform() * local_pos)
|
||||
get_tree().input_event(ie)
|
||||
ie.position = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos
|
||||
Input.parse_input_event(ie)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
var localPos = new Vector2(10,20); // local to Control/Node2D
|
||||
var localPos = new Vector2(10,20); // Local to Control/Node2D.
|
||||
var ie = new InputEventMouseButton()
|
||||
{
|
||||
ButtonIndex = MouseButton.Left,
|
||||
Position = GetViewportTransform() * (GetGlobalTransform() * localPos),
|
||||
Position = GetViewport().GetScreenTransform() * GetGlobalTransformWithCanvas() * localPos,
|
||||
};
|
||||
GetTree().InputEvent(ie);
|
||||
Input.ParseInputEvent(ie);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
BIN
tutorials/2d/img/viewport_transforms3.webp
Normal file
BIN
tutorials/2d/img/viewport_transforms3.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Reference in New Issue
Block a user