Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Преобразование области просмотра и холста
Введение
Это обзор 2D-преобразований, происходящих для узлов с момента, когда они рисуют свое содержимое локально, до момента, когда они рисуются на экране. В этом обзоре обсуждаются очень низкоуровневые детали движка.
Цель этого руководства - научить Вас способу передачи событий ввода в Input с позицией в правильной системе координат.
Более подробное описание всех систем координат и 2D-преобразований доступно в Двумерные системы координат и двумерные преобразования.
Преобразования холста
Как упоминалось в предыдущем руководстве Слои холста, каждый узел CanvasItem (помните, что узлы на основе Node2D и Control используют CanvasItem в качестве общего корня) будет находиться в Canvas Layer. Каждый слой холста имеет преобразование (перемещение, поворот, масштаб и т.д.), к которому можно получить доступ как Transform2D.
Как было сказано в предыдущем уроке, узлы по умолчанию рисуются на 0-ом слое на встроенном холсте. Для того, чтобы поместить узлы на другой слой, можно воспользоваться узлом CanvasLayer.
Глобальное преобразование холста
У вьюпортов также есть Global Canvas transform (Глобальное преобразование Холста) (также Transform2D). Это главное преобразование, которое влияет на все отдельные преобразования Canvas Layer. Как правило, оно в основном используется в редакторе CanvasItem редактора Godot.
Преобразования растяжения
Наконец, в видовых экранах есть функция Stretch Transform, которая используется при изменении размера или растягивании экрана. Это преобразование используется внутренне (как описано в Несколько резолюций), но также может быть вручную установлено для каждого видового экрана.
События ввода умножаются на это преобразование, но не имеют тех, что выше. Для преобразования координат InputEvent в локальные координаты CanvasItem для удобства была добавлена функция CanvasItem.make_input_local().
Трансформация окна
Корневое окно просмотра представляет собой Окно. Чтобы масштабировать и позиционировать содержимое окна в соответствии с описанным в Несколько резолюций, каждое окно содержит оконное преобразование. Оно, например, отвечает за черные полосы по краям окна, чтобы Окно просмотра отображалось с фиксированным соотношением сторон.
Порядок преобразований
Чтобы преобразовать локальную координату CanvasItem в фактическую экранную координату, необходимо применить следующую цепочку преобразований:
Функции преобразования
График выше показывает некоторые доступные функции преобразования. Все преобразования выполняются справа налево, что означает: умножение преобразования на координату смещает систему координат влево, а умножение аффинного обратного преобразования смещает систему координат вправо:
# Called from a CanvasItem.
canvas_pos = get_global_transform() * local_pos
local_pos = get_global_transform().affine_inverse() * canvas_pos
// Called from a CanvasItem.
canvasPos = GetGlobalTransform() * localPos;
localPos = GetGlobalTransform().AffineInverse() * canvasPos;
Наконец, чтобы преобразовать локальные координаты CanvasItem в экранные координаты, просто умножьте в следующем порядке:
var screen_coord = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos
var screenCoord = GetViewport().GetScreenTransform() * GetGlobalTransformWithCanvas() * localPos;
Однако имейте в виду, что обычно нежелательно работать с экранными координатами. Рекомендуемый подход - просто работать в координатах холста (CanvasItem.get_global_transform ()), чтобы автоматическое изменение размера разрешения экрана работало правильно.
Передача пользовательских событий ввода
Часто требуется передавать пользовательские события ввода в игру. С учетом вышеизложенных знаний, чтобы правильно сделать это в сфокусированном окне, это должно быть сделано следующим образом:
var local_pos = Vector2(10, 20) # Local to Control/Node2D.
var ie = InputEventMouseButton.new()
ie.button_index = MOUSE_BUTTON_LEFT
ie.position = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos
Input.parse_input_event(ie)
var localPos = new Vector2(10,20); // Local to Control/Node2D.
var ie = new InputEventMouseButton()
{
ButtonIndex = MouseButton.Left,
Position = GetViewport().GetScreenTransform() * GetGlobalTransformWithCanvas() * localPos,
};
Input.ParseInputEvent(ie);