Viewport- und Canvas-Transformationen
Einführung
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.
Das Ziel dieses Tutorials ist es, eine Methode zu vermitteln, wie man Eingabeereignisse mit einer Position im richtigen Koordinatensystem an den Input weiterleitet.
Eine ausführlichere Beschreibung aller Koordinatensysteme und 2D-Transformationen finden Sie in 2D-Koordinatensysteme und 2D-Transformationen.
Canvas-Transformation
Wie in der vorherigen Anleitung Canvas-Ebenen erwähnt, befindet sich jeder CanvasItem-Node in einer Canvas-Ebene (denken Sie daran, dass Node2D- und Control-basierte Nodes CanvasItem als gemeinsamen Root verwenden). Jede Canvas-Ebene verfügt über eine Transformation (Verschiebung, Drehung, Skalierung usw.), auf die wie folgt zugegriffen werden kann Transform2D.
Ebenfalls im vorherigen Kapitel behandelt, werden Nodes standardmäßig in Ebene 0 im Built-in-Canvas gezeichnet. Um Nodes in einer anderen Ebene zu platzieren, kann ein CanvasLayer-Node verwendet werden.
Globale Canvas-Transformation
Viewports haben auch eine globale Canvas-Transformation (auch eine Transform2D). Dies ist die Master-Transformation und beeinflusst alle individuellen Canvas Layer Transformationen. Im Allgemeinen wird dies hauptsächlich im CanvasItem-Editor von Godot verwendet.
Stretch-Transformation
Schließlich verfügen Ansichtsfenster über eine Stretch-Transformation, die beim Ändern der Größe oder Strecken des Bildschirms verwendet wird. Diese Transformation wird intern verwendet (wie in Mehrere Auflösungen beschrieben), kann aber auch manuell für jeden Viewport festgelegt werden.
Input events are multiplied by this transform, but lack the ones above. To convert InputEvent coordinates to local CanvasItem coordinates, the CanvasItem.make_input_local() function was added for convenience.
Window-Transformation
Der Root-Viewport ist ein Window. Um den Inhalt des Windows wie in Mehrere Auflösungen beschrieben zu skalieren und zu positionieren, enthält jedes Window eine Window-Transformation. Sie ist z.B. für die schwarzen Balken an den Seiten des Windows verantwortlich, damit der Viewport mit einem festen Seitenverhältnis dargestellt wird.
Transformationsreihenfolge
Um eine lokale CanvasItem-Koordinate in eine tatsächliche Bildschirmkoordinate umzuwandeln, muss die folgende Kette von Transformationen angewendet werden:
Transformationsfunktionen
Die obige Grafik zeigt einige verfügbare Transformationsfunktionen. Alle Transformationen sind von rechts nach links gerichtet, d.h. die Multiplikation einer Transformation mit einer Koordinate ergibt ein weiter links liegendes Koordinatensystem, die Multiplikation der affinen Inversen einer Transformation ergibt ein weiter rechts liegendes Koordinatensystem:
# 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;
Um die lokalen CanvasItem-Koordinaten in Bildschirmkoordinaten umzuwandeln, multiplizieren Sie sie einfach in der folgenden Reihenfolge:
var screen_coord = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos
var screenCoord = GetViewport().GetScreenTransform() * GetGlobalTransformWithCanvas() * localPos;
Beachten Sie jedoch, dass es im Allgemeinen nicht erwünscht ist, mit Bildschirmkoordinaten zu arbeiten. Der empfohlene Ansatz besteht darin, einfach in Canvas-Koordinaten (CanvasItem.get_global_transform()) zu arbeiten, damit die automatische Größenänderung der Bildschirmauflösung ordnungsgemäß funktioniert.
Benutzerdefinierte Eingabeereignisse weiterleiten
Oft ist es erwünscht, benutzerdefinierte Eingabeereignisse an das Spiel weiterzuleiten. Mit dem obigen Wissen muss dies im fokussierten Fenster auf die folgende Weise geschehen:
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);