Viewport 與 Canvas 變換

簡介

本頁介紹了節點從其內容在本機被繪製一直到被繪製到畫面上的 2D 變換過程。本概覽也討論了有關引擎非常低階的細節。

Canvas 變換

與之前的教學,ref:doc_canvas_layers,提到的一樣,所有 CanvasItem 節點 (請記得,基於 Node2D 與 Control 的節點都使用 CanvasItem 作為共同的基礎型別) 會被保持放在 Canvas Layer 中。所有的 Canvas Layer 都有可作為 Transform2D 存取的變換 (平移、旋轉、縮放…等)。

另外,在之前的教學中也有提到,節點預設會在內建 Canvas 的 Layer 0 中繪製。若要將節點放在不同的圖層中,可使用 CanvasLayer 節點。

全域 Canvas 變換

Viewport 也有一個全域 Canvas 變換 (該變換也是 Transform2D)。全域 Canvas 為主變換,會影響所有單獨的 Canvas Layer 變換。一般來說,這種變換並不常用,但在 Godot 編輯器中的 CanvasItem 編輯器中有用到。

拉伸變換

最後,Viewport 還有 拉伸變換 (Stretch Transform) ,該變換時用來縮放或拉伸螢幕的。這個變換時在內部使用的 (與 Multiple resolutions 中說明的一樣),但也可以手動在各個 Viewport 上設定。

有接受 MainLoop._input_event() 回呼的輸入事件也會受到該變換加成,但並不屬於上述變換。若要將 InputEvent 座標轉換為本機 CanvasItem 座標,我們提供了方便的 CanvasItem.make_input_local() 函式。

變換順序

要將 CanvasItem 本機屬性內的座標轉換為實際螢幕上的座標,必須要套用下列一系列的變換:

../../_images/viewport_transforms2.png

變換函式

可以通過下列方法來取得各個變換:

型別

變換

CanvasItem

CanvasItem.get_global_transform()

CanvasLayer

CanvasItem.get_canvas_transform()

CanvasLayer+GlobalCanvas+Stretch

CanvasItem.get_viewport_transform()

最後,要將 CanvasItem 本機座標轉換為螢幕座標,只需要以下列順序相乘:

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

請記得,我們通常不會使用到螢幕座標。建議的做法是只要處理 Canvas 座標就好了 (CanvasItem.get_global_transform()),使用 Canvas 座標就可以自動處理好不同的螢幕解析度縮放。

處理自定輸入事件

很多情況下我們會想將自定輸入事件提供給場景樹。有了上述知識,若要正確將自定輸入事件提供給場景樹,則必須要通過下列方法:

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