Viewport and canvas transforms

Introduction

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.

Canvas transform

Canvas layers, every CanvasItem node (remember that Node2D and Control based nodes use CanvasItem as their common root) will reside in a Canvas Layer. Every canvas layer has a transform (translation, rotation, scale, etc.) that can be accessed as a Transform2D. CanvasLayer node can be used.

Global canvas transform

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.

Stretch transform

Stretch Transform, which is used when resizing or stretching the screen. This transform is used internally (as described in Multiple resolutions), but can also be manually set on each viewport. MainLoop._input_event() callback 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.

Transform order

For a coordinate in CanvasItem local properties to become an actual screen coordinate, the following chain of transforms must be applied:

Transform functions

Obtaining each transform can be achieved with the following functions: Finally, then, to convert a CanvasItem local coordinates to screen coordinates, just multiply in the following order: GDScript C#

  1. var screen_coord = get_viewport_transform() * (get_global_transform() * local_pos)
  1. var screenCord = (GetViewportTransform() * GetGlobalTransform()).Xform(localPos);

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: GDScript C#

  1. var local_pos = Vector2(10, 20) # local to Control/Node2Dvar ie = InputEventMouseButton.new()ie.button_index = BUTTON_LEFTie.position = get_viewport_transform() * (get_global_transform() * local_pos)get_tree().input_event(ie)
  1. var localPos = new Vector2(10,20); // local to Control/Node2Dvar ie = new InputEventMouseButton();ie.ButtonIndex = (int)ButtonList.Left;ie.Position = (GetViewportTransform() * GetGlobalTransform()).Xform(localPos);GetTree().InputEvent(ie);