I’m making an application for editing certain files. At some point in my app, there is a list of items: clicking on an item opens an interface for editing it. In the list, I want to show a little visual preview for each item, so it’s visually easy to find the item you want to edit. The thing is, these items are made of 2D nodes (and my UI is made of Control nodes).
I could instantiate all the items in a separate viewport and have one SubViewportContainer for each preview, but I doubt this would perform well with thousands of items.
Perhaps I could pre-render all the items beforehand. How would that work?
Or is there a neat built-in solution I haven’t noticed?
Of course I know we can mix Control and Node2D, but as you should know, we can’t use anchors and/or containers on a Node2D.
So, I wrote a function that manually positions and scales a Node2D to fit inside some preview rectangle.
func _fit_inside_preview_rect(preview_rect: Rect2D) -> void:
# Assuming you know the leftmost_point, rightmost_point,
# topmost_point and bottommost_point of your node...
var width: float = rightmost_point - leftmost_point
var height: float = bottommost_point - topmost_point
# Prevent division by zero
if width == 0.0 or height == 0.0:
return
# Determine the scale ratio (e.g. if the node
# is 3x bigger than it should be, then we need to scale by 1/3)
# To preserve the aspect ratio,
# we need to multiply by the smallest of the two ratios.
var scale_ratio: float = (
minf(preview_rect.size.x / width, preview_rect.size.y / height)
)
position = Vector2(
preview_rect.position.x - leftmost_point * scale_ratio,
preview_rect.position.y - topmost_point * scale_ratio
)
scale = Vector2(scale_ratio, scale_ratio)
It does work. It feels a bit hacky, though. I wish there was a built-in way to do this without code.