- this post covers
- introduction to widget coordinate system
- what is
FGeometry
is - how to get transform of widget
- the meaning of each part of transform
- tips for manipulating widget transform
- environment
- Unreal Engine (4.24)
- Visual Studio 2017
- Windows 10
- reference
widget coordinate system
suppose you have a game window. it might look like the picture and focus onto the popup widget
in this condition, we can call the coordinate system as Window Space
Window Space
- a space has an origin with left-top of window
- we can use this coordinate system for getting certain position in window
even we can imagine the coordinate system Monitor Space
Monitor Space
- a space has an origin with left-top of monitor
- we can use this coordinate system for getting certain position in monitor
※ position values are approximate
※ these terms are not official. they are just used for explaining this post
FGeometry
introduction
1 | UnrealEngine/Engine/Source/Runtime/SlateCore/Public/Layout/Geometry.h |
- in unreal engine,
FGeometry
can help getting those transforms mentioned above - the
FGeometry
- contains useful data for widget especially the transform
- is updated whenever widget is painted or ticked
- every variance to transform is accumulated in
FGeometry
- in short, each tick, every widget has latest information for calculating transform
1 | UnrealEngine/Engine/Source/Runtime/SlateCore/Private/Widgets/SWidget.h |
1 | UnrealEngine/Engine/Source/Runtime/SlateCore/Private/Widgets/SWidget.cpp |
- we can get
FGeometry
object viaSWidget::Get*Geometry()
series- FYI,
SWidget::GetCachedGeometry()
has been deprecated from 4.23
- FYI,
- for general purpose, you can use any getter
DesktopGeometry
andAllottedGeometry
are not that different- but unreal engine recommend you to use
AllottedGeometry
one
※ for more information, visit reference #1 + reference #2 + reference #3
FGeometry
APIs
GetLocalSize()
1 | UnrealEngine/Engine/Source/Runtime/SlateCore/Public/Layout/Geometry.h |
returns a size in local space. this size is usually determined with value set in editor
GetAbsoluteSize()
1 | UnrealEngine/Engine/Source/Runtime/SlateCore/Public/Layout/Geometry.h |
returns a size in outer space. this size is based on your screen, which is real size
LocalToViewport()
1 | UnrealEngine/Engine/Source/Runtime/UMG/Public/Blueprint/SlateBlueprintLibrary.h |
returns positions in outer space and local space respectively with parameters, which are PixelPosition
and ViewportPosition
LocalToAbsolute()
1 | UnrealEngine/Engine/Source/Runtime/UMG/Public/Blueprint/SlateBlueprintLibrary.h |
returns a position in Monitor Space
how to use
those APIs can be used for calculating transform. let us find out how to use them
Child | Position | Size | Parent |
---|---|---|---|
Red One | (100, 50) | (60, 30) | Canvas Panel #1 |
Green One | (0, 0) | (60, 30) | Canvas Panel #2 |
Blue One | NaN | (60, 30) | Horizontal Box |
White One | NaN | (60, 30) | Horizontal Box |
we gotta use this widget for example. the widget has children with multiple depth. each editor property of child is above
※ transform property can be divided into local and absolute due to DPI Scale
※ in this example(and also default value), we got DPI Scale = 2/3
which means that every property gets multiplied with 0.666666…
Window Space
- widget
- size
- local =
Widget->GetCachedGeometry()->GetLocalSize()
- absolute =
Widget->GetCachedGeometry()->GetAbsoluteSize()
(60, 30) * 0.666666… ≒ (39.99996…, 19.99998…)
- local =
- position
- local =
Widget->GetCachedGeometry()->LocalToViewport()->ViewportPosition
- absolute =
Widget->GetCachedGeometry()->LocalToViewport()->PixelPosition
(100, 50) * 0.666666… ≒ (66.66666…, 33.33333…)
- local =
- size
- widget
verification (with Adobe Photoshop)
- widget
- size
- position
- widget
Monitor Space
- window
- size
- local approximately 1920x1080
- absolute (1920, 1080) * 0.666666… = (1280, 720)
- position
- local cannot calculate. also not meaningful, unless the `DPI Scale` is the same with system's one
- absolute
- size
- widget
- size
the same with before - position
- local
cannot calculate. also not meaningful, unless theDPI Scale
is the same with system’s one - absolute
- local
- size
- window
verification (with Adobe Photoshop)
- window
- size
- position
- widget
- size
the same with before - position
- size
- window
Window Space
summary
Property | Widget |
---|---|
Size.Local | (60, 30) |
Size.Absolute | (40, 20) |
Position.Local | (100, 50) |
Position.Absolute | (66, 33) |
Monitor Space
summary
Property | Window | Widget |
---|---|---|
Size.Local | (1920, 1080) | (60, 30) |
Size.Absolute | (1280, 720) | (40, 20) |
Position.Local | NaN | NaN |
Position.Absoulte | (640, 350) | (640 + 66, 350 + 33) = (706, 383) |
widget translation
suppose you have to translate a widget into certain position. how will you ?
first, we need to check whether the slot of widget has SetPosition
API. if the slot does not, we cannot do widget translation
but we can do it, as the red image was in Canvas Panel
1 | UnrealEngine/Engine/Source/Runtime/UMG/Public/Components/CanvasPanelSlot.h |
1 | UnrealEngine/Engine/Source/Runtime/UMG/Public/Components/CanvasPanelSlot.cpp |
the parameter InPosition
should be local position. it is easy to think, this is the same work with changing value in editor
second, we need to get local position of the widget. let us use the example red image again
in previous example, red image had a local position of (100, 50) in Window Space
let us move the widget with offset (100, 50) again
third, we need to set local position with new one. in this time, SetPosition(200, 100)
will be needed
and we gotta check a local position at next tick. the local position would be (200, 100) and absolute position also be twice
- verification (with Adobe Photoshop)
- size
the same with before - position
- absolute position in
Window Space
- absolute position in
Monitor Space
- absolute position in
- size
wrap-up !
- getting local or absolute position is usually possible regardless of layout of widget such as widget hierarchy
- we can only set local position through the API of slot such as
Canvas Panel Slot
- you need to calculate new position (based on several conditions, especially
DPI Scale
) to translate widget into desired position