Does anyone know a way to get the location of a widget in screenspace?
I’ve got a bunch of buttons that spawn into a scrollbox, and I want to pop a contextual menu up on the location of each button when pressed. The only function I see i that looks like the correct one is getting the widget transform, but it appears to spit out 0,0 for every item within the scrollbox. I’m guessing it’s because it’s outputting it’s own transform relative to itself, which seems correct as 0,0.
Getting the slot from the scrollbox doesn’t seem to work either… I don’t see any functions related to transform, viewport, screen, or anything when getting a slot. Same with the render transform when I get a child of the scrollbox… it’s always 0,0.
Any help or guidance would be appreciated. I’m attaching an image to better illustrate what I’m trying to accomplish.
Screenspace location is only known in events that have blue geometry node in UMG.
If you drag from it there are some nodes in context list.
I do not remember exactly now, but i think those events are on construct and on draw in event graph of umg hud. This thing is also quite complicated, or undocumented, or just messy.
(I am not sure yet which one is the case here).
And be careful because input coordinates (from mouse or touch) are different from world space (calculated as world to umg coordinates), and umg space, so you have 3 differently scaled areas (also different aspect ratios).
Thanks! Good to know. Looks like I’ll need to put it on tick, since I there aren’t any other events that I can use that’ll work with controller & mouse/keyboard.
Yeah, the problem is that I’m manually setting focus on widgets in a scroll box using an index since I need controller input. The buttons never get hovered or mouse events, they just get their properties set based on manually managing what should have focus.
It’s not simple. Slate does not allow access to widget geometry outside of the event/layout pass where the geometry is stable and you can make the correct calculations without introducing layout loops. The only widget who gives you access to their geometry is your own, during the Tick or the events where the geometry is available.
This is what I’ve been playing around with. For now I’m just outputting to a print string. I’d assume that converting 0,0 in the geometry from local to absolute would return the upper left corner of the widget in screen space. My test case has a widget embedded in a border, and the tick->geometry check is being performed by the widget within the border.
That value should be 124,124 in my test scenario. The value I’m getting is 433,284, which is the location of the yellow circle in the attached image. I can manually mess with values from that to push that dot back to the location I want via trial and error, but if I could figure out how those values are created, I could probably come up with something more reliable. I’m obviously misunderstanding something here… but I can’t figure out what.
Ok… so it looks like the values it outputs assumes a 1080p resolution. When I full screen and test at 1080p, I get the values I would expect. I guess I need to multiply the output values against the resolution scale of the current UI.
The absolute coordinate is in desktop space that’s why it works in fullscreen. You’d need remove the viewport’s inverse transform, to get it in viewport space. Though I don’t know if that transform is readily available.
I’ve added some utility functions to ML to help with this in the future, if you want to grab the code and throw it into your own utility BP library, here’s the changelist.
The functions will give you the position in both viewport space and screen space. viewport is like pre DPI scaling space of widgets. Screen is, canvas land, pixels, ray casting land…etc.