31 lines
1.1 KiB
GDScript3
31 lines
1.1 KiB
GDScript3
|
|
class_name ViewUtils
|
||
|
|
extends RefCounted
|
||
|
|
|
||
|
|
# Computes the exact world-space rect currently visible on screen by
|
||
|
|
# transforming the viewport's real screen corners through the actual canvas
|
||
|
|
# transform, instead of approximating with viewport_size * camera.zoom
|
||
|
|
# (which assumes a simple centered mapping - stretch/aspect="expand" doesn't
|
||
|
|
# necessarily expand symmetrically around center, which was making that
|
||
|
|
# approximation under/over-shoot on one side and cull content that was
|
||
|
|
# actually on screen).
|
||
|
|
static func get_visible_world_rect(node: Node) -> Rect2:
|
||
|
|
var canvas_transform: Transform2D = node.get_viewport().get_canvas_transform()
|
||
|
|
var inverse: Transform2D = canvas_transform.affine_inverse()
|
||
|
|
var size: Vector2 = node.get_viewport_rect().size
|
||
|
|
|
||
|
|
var corners: Array = [
|
||
|
|
inverse * Vector2(0, 0),
|
||
|
|
inverse * Vector2(size.x, 0),
|
||
|
|
inverse * Vector2(0, size.y),
|
||
|
|
inverse * Vector2(size.x, size.y),
|
||
|
|
]
|
||
|
|
|
||
|
|
var min_pt: Vector2 = corners[0]
|
||
|
|
var max_pt: Vector2 = corners[0]
|
||
|
|
for c in corners:
|
||
|
|
min_pt.x = min(min_pt.x, c.x)
|
||
|
|
min_pt.y = min(min_pt.y, c.y)
|
||
|
|
max_pt.x = max(max_pt.x, c.x)
|
||
|
|
max_pt.y = max(max_pt.y, c.y)
|
||
|
|
|
||
|
|
return Rect2(min_pt, max_pt - min_pt)
|