Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Transformación de Viewport y Canvas

Introducción

Esto es un resumen de lo que sucede con las matrices de transformación 2D en los nodos desde el momento en que dibujan su contenido localmente hasta el momento en que se muestran en pantalla. Aquí se mostrarán detalles de muy bajo nivel de el motor.

El objetivo de este tutorial es enseñar una manera de enviar eventos de entrada al Input con una posición en el sistema de coordenadas correcto.

Una descripción más extensa de todos los sistemas de coordenadas y transformaciones 2D está disponible en 2D coordinate systems and 2D transforms.

Transformación del canvas

Como se mencionó en el tutorial anterior, Capas de Canvas, cada nodo CanvasItem (recuerda que los nodos basados en Node2D y Control usan CanvasItem como su raíz común) residirá en una Canvas Layer. Cada canvas layer tiene una transformación (translation, rotation, scale, etc.) a la que se puede acceder mediante Transform2D.

Esto también está cubierto por el tutorial anterior, los nodos son dibujados por defecto en Layer (capa) 0, en el "built-in canvas" (el canvas por defecto del viewport). Para colocar nodos en una capa distinta, se debe utilizar una CanvasLayer.

Transformación global del canvas

Los Viewports también tienen una transformación Global Canvas (también un Transform2D). Esta es la transformación principal y afecta a todas las transformaciones individuales de Canvas Layer. Generalmente esta transformación es usada en el Editor de CanvasItem de Godot.

Transformación de estiramiento

Por último, los Viewports tienen un Stretch Transform, que se utiliza al cambiar de tamaño o estirar la pantalla. Esta transformación se utiliza internamente (como se describe en Múltiples resoluciones) pero también se puede configurar manualmente en cada Viewport.

Los eventos de entrada son multiplicados por este transform, pero carecen de los presentados anteriormente. Para convertir las coordenadas de InputEvent a locales de CanvasItem, se agregó la función CanvasItem.make_input_local().

Transform de Window

El viewport raíz es una :ref: Window. Para poder escalar y posicionar el contenido de Window's como se describe en Múltiples resoluciones, cada Window contiene un window transform. Este es, por ejemplo, responsabe por las barras negras a los costados de Window's así el Viewport se muestra con una relación de aspecto fija.

Orden de Transform

Para convertir un sistema de coordenadas locales de CanvasItem en coordenadas de pantalla, se debe aplicar la siguiente secuencia de transforms:

../../_images/viewport_transforms3.webp

Funciones de Transform

El gráfico superio murstra las funciones de tranformacion disponibles. Todas las transformaciones se realizan de derecha a izquierda, esto significa que multiplicar una transformación con una coordenada resulta en un sistema de coordenadas más hacia la izquierda, multiplicar el :ref:`affine inverse <class_Transform2D_method_affine_inverse>`de una transformación resulta en un sistema de coordenadas más hacia la derecha:

# Called from a CanvasItem.
canvas_pos = get_global_transform() * local_pos
local_pos = get_global_transform().affine_inverse() * canvas_pos

Finalmente, para convertir un CanvasItem de coordenadas locales a coordenadas de pantalla, utilizar el siguiente orden:

var screen_coord = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos

Tener en cuenta que esto no es aconsejable para trabajar en coordenadas de pantalla. Lo recomendable es simplemente trabajar en coordenadas de Canvas (CanvasItem.get_global_transform()), para permitir que el cambio de tamaño/ajuste de resolución funcione de la manera adecuada.

Generando eventos de entrada personalizados

Usualmente es deseable crear eventos de entradas personalizados para el juego. Con lo aprendido anteriormente, para hacerlo de manera correcta en la ventana enfocada, se debe hacer lo siguiente:

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)