Ok, so I have a node tree in my main scene that is like this (simplified)
root
|- LevelHolder
|- Player
|- Camera2D
|- CanvasLayer
|- SomeUI
|- ...
|- Extents
|- TopLeft
|- BottomRight
And the situation I have is that my Canvas Layer has a full rect layout to stretch across the screen, and then my SomeUI element contains a bunch of UI elements that make up a HUD and a frame. I've got a Camera2D that allows me to zoom in and out on my player and level, so the editor's placement of the Node2D elements doesn't match the in-game view, since the Camera moves and zooms.
I don't want my player to be able to move underneath my HUD elements, so I've got these Extents objects in the CanvasLayer, which I can anchor to the top-left and bottom-right corners of the part of my HUD that I actually want the player to be able to walk around in.
So what I think I need to do is turn Canvas positions into positions I can set for my player.
After a lot of trial and error, this is what worked for me:
var tl = $CanvasLayer/Extents/TopLeft
var tlgp = tl.get_viewport_transform() * tl.get_global_transform()
$Player.topleft = self.get_viewport_transform().affine_inverse().xform(tlgp.origin)
var br = $CanvasLayer/Extents/BottomRight
var brgp = br.get_viewport_transform() * br.get_global_transform()
$Player.bottomright = self.get_viewport_transform().affine_inverse().xform(brgp.origin)
Which works, but seems like a lot of work, and it took me a lot of screwing around to find this all. And I can leave out self.get_global_transform() in this case because I know that root's global transform is the identity, but in general it'd be even more complicated.
So, my real question is have I just overcomplicated this? Is there some method I could use that would just do all of this for me (or something else entirely) that would let me easily place a Node2D underneath a Canvas element, no matter what size the window is, or how it's stretched or squashed?