본문 바로가기

Development/Unreal Engine 4, 5

Slate UI C++ Example

Tutorial index

Unreal Engine 4: Slate UI Tutorial 3: nested components

In this tutorial we will look at how you can place more than one components on an overlay, and how to nest the components to organize your UI more efficiently. Furthermore, a complete list of the slate components provided by the engine can be found at the bottom of the page, with a brief description of each one.

Disclaimer: information provided in this tutorial on positioning of widgets and the overal behavior of the slate system is the result of observations and experimentations.

To begin with, to nest widgets you need a widget that can house other widgets within it. SHorizontalBox and SVerticalBox are two such widgets which you are likely to use a lot. They create an imaginary box in which widgets are added in a horizontal or vertical alignment. You could nest multiple SHorizontalBoxes in an SVerticalBox or vice-versa to create a grid. Let's go to the point where we started adding widgets and create a vertical box:

ChildSlot.VAlign(VAlign_Fill).HAlign(HAlign_Fill)
[
    SNew(SVerticalBox)
    + SVerticalBox::Slot()
    .HAlign(HAlign_Left)
    .VAlign(VAlign_Center)
    [
    ]
];

This vertical box is the root component (I can't guarantee that is the official terminology). To add components within it, we add slots, taken from the SVerticalBox namespace. The first slot we create is alligned to the left horizontally, meaning it will try to stay on the left side as other widgets are added on the same level as itself, and on the center vertically, equivalently meaning it will try to remain on the center between other widgets in the same parent container. Within the brackets [] we can add as many other components as we wish. Let's populate this slot with a textbox, let's assume this to be the pause menu, so we'll add an appropriate text. Formatting and styling are covered in the next tutorials, so don't worry if the text is too small.


SNew(SVerticalBox)
+ SVerticalBox::Slot()
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
[
     SNew(STextBlock)
    .ShadowColorAndOpacity(FLinearColor::Black)
    .ColorAndOpacity(FLinearColor::Red)
    .ShadowOffset(FIntPoint(-1, 1))
    .Font(FSlateFontInfo("Verdana", 16))
    .Text(FString("Pause Menu"))
]

To be honest, I just picked up the textbox from the previous tutorial and dropped it in, placing the right text in the output. So now you've got some text, but that doesn't really demonstrate much on nesting widgets. So let's put an SHorizontalBox inside that:


SNew(SVerticalBox)
+ SVerticalBox::Slot()
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
[
     SNew(STextBlock)
     .ShadowColorAndOpacity(FLinearColor::Black)
     .ColorAndOpacity(FLinearColor::Red)
     .ShadowOffset(FIntPoint(-1, 1))
     .Font(FSlateFontInfo("Verdana", 16))
     .Text("Pause Menu")
]
+ SVerticalBox::Slot()
.VAlign(VAlign_Center)
[
     SNew(SHorizontalBox)
     + SHorizontalBox::Slot()
     .HAlign(HAlign_Left)
     .VAlign(VAlign_Top)
     [
          SNew(STextBlock)
          .ShadowColorAndOpacity(FLinearColor::Black)
         .ColorAndOpacity(FLinearColor::Red)
         .ShadowOffset(FIntPoint(-1, 1))
         .Font(FSlateFontInfo("Verdana", 16))
         .Text(FString("Options:"))
     ]
]

There! Ok, but what do we expect to see?

Screen space distribution:

Slate doesn't exactly clear up where things will wind up being. The important thing to remember is that things are nested, meaning that once the distribution of the outer items is done, the inner items are distributed within their parents as if their parents were the entire screen. This does not mean that the parent will not grow to accomodate more data, but rather that you will have the hierarchy treated with respect. Let's look at the case above. You have a vertical box, which is to be in the center-left. It is however the only widget at its level, meaning that it may well expand to take up the entire screen, though it will prefer the center left part. Within it, you have 1) a text block and 2) a horizontal box. These have to share the space of their parent, the parent dictating that they will be distributed vertically. This means that all components are stacked one below the other, in the order given. These nested widgets' alignment concerns the area allocated to them, not their position in their parent area, which is determined, as stated just now, by the order they are added to it. Finally the new text block in the horizontal box is placed in the area of the horizontal box, rather than as a third element in the vertical box. To make things more apparent, copy-paste pieces of code to create larger UI structures:


SNew(SVerticalBox)
+ SVerticalBox::Slot()
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
[
     SNew(STextBlock)
     .ShadowColorAndOpacity(FLinearColor::Black)
     .ColorAndOpacity(FLinearColor::Red)
     .ShadowOffset(FIntPoint(-1, 1))
     .Font(FSlateFontInfo("Verdana", 16))
     .Text("Pause Menu")
]
+ SVerticalBox::Slot()
.VAlign(VAlign_Center)
[
     SNew(SHorizontalBox)
     + SHorizontalBox::Slot()
     .HAlign(HAlign_Left)
     .VAlign(VAlign_Top)
     [
          SNew(STextBlock)
          .ShadowColorAndOpacity(FLinearColor::Black)
         .ColorAndOpacity(FLinearColor::Red)
         .ShadowOffset(FIntPoint(-1, 1))
         .Font(FSlateFontInfo("Verdana", 16))
         .Text(FString("Options:"))

          SNew(STextBlock)
          .ShadowColorAndOpacity(FLinearColor::Black)
         .ColorAndOpacity(FLinearColor::Red)
         .ShadowOffset(FIntPoint(-1, 1))
         .Font(FSlateFontInfo("Verdana", 16))
         .Text(FString("Game:"))

          SNew(STextBlock)
          .ShadowColorAndOpacity(FLinearColor::Black)
         .ColorAndOpacity(FLinearColor::Red)
         .ShadowOffset(FIntPoint(-1, 1))
         .Font(FSlateFontInfo("Verdana", 16))
         .Text(FString("Info:"))
     ]
+ SVerticalBox::Slot()
.VAlign(VAlign_Center)
[
     SNew(SHorizontalBox)
     + SHorizontalBox::Slot()
     .HAlign(HAlign_Left)
     .VAlign(VAlign_Top)
     [
          SNew(STextBlock)
          .ShadowColorAndOpacity(FLinearColor::Black)
         .ColorAndOpacity(FLinearColor::Red)
         .ShadowOffset(FIntPoint(-1, 1))
         .Font(FSlateFontInfo("Verdana", 16))
         .Text(FString("Options2:"))

          SNew(STextBlock)
          .ShadowColorAndOpacity(FLinearColor::Black)
         .ColorAndOpacity(FLinearColor::Red)
         .ShadowOffset(FIntPoint(-1, 1))
         .Font(FSlateFontInfo("Verdana", 16))
         .Text(FString("Game2:"))

          SNew(STextBlock)
          .ShadowColorAndOpacity(FLinearColor::Black)
         .ColorAndOpacity(FLinearColor::Red)
         .ShadowOffset(FIntPoint(-1, 1))
         .Font(FSlateFontInfo("Verdana", 16))
         .Text(FString("Info2:"))
     ]
]

Try using such a code and see what happens! See if you can predict where each item will go by changing their text to "Center-left", "Lower-right" and so on. Practice makes perfect!

 

Below follows a list of basic slate components supported by Engine Version 4.8.3:

SBorder
SBox
SBoxPanel
SBreadcrumTrail
SBuuildProgressWidget
SButton
SCanvas
SCheckBox
SComboBox
SComboButton
SComboRow
SColorBlock
SColorSpectrum
SColorWheel
SCompoundWidget
SDPIScaler
SEditableComboBox
SEditableText
SEditableTextBox
SErrorHint
SErrorText
SExpandableArea
SExpandableButton
SExpanderArrow
SFxWidget
SGraphNode
SGridPanel
SHeader
SHeaderRow
SHorizontalBox
SHyperlink
SImage
SInlineEditableTextBlock
SLeafWidget
SListPanel
SListView
SMenuAnchor
SMissingWidget
SMultiBlockBaseWidget
SMultiBoxWidget
SMultiColumnTableRow
SMultiLineEditableText
SMultiLineEditableTextBox
SNotificationItem
SNotificationList
SNulWidget
SNumericEntryBox
SOverlay
SPanel
SPopup
SPopupErrorText
SPopupLayer
SProgressBar
SRichTextBlock
SRichTextHyperlink
SRotatorInputBox
SSafezone
SScrollBar
SScrollBarTrack
SScrollBorder
SScrollBox
SSearchBox
SSeparator
SSlider
SSpacer
SSpinBox
SSpinningImage
SSpliter
SSpliter2x2
SSuggestionTextBox
STableRow
STableViewBase
STextBlock
STextComboBox
STextComboPopup
STextEntryPopup

 

 

 

http://students.ceid.upatras.gr/~vpapadatos/UE4cpp_slate_3_nestingWidgetsAndCapabilities.html

 

UE4 Slate UI tutorial 3 - Nested Widget + List of Widgets

SNew(SVerticalBox) + SVerticalBox::Slot() .HAlign(HAlign_Left) .VAlign(VAlign_Center) [      SNew(STextBlock)      .ShadowColorAndOpacity(FLinearColor::Black)      .ColorAndOpacity(FLinearColor::Red)      .ShadowOffset(FIntPoint(-1, 1))  

students.ceid.upatras.gr

 

 

 

http://students.ceid.upatras.gr/~vpapadatos/TutorialCentral.html

 

Tutorial Cental - Homer Papadatos-Vasilakis

Tutorials XNA Framework The XNA framework, though not maintained in quite a while, is a complete DirectX wrapper for C# developed officially by Microsoft. It formed the foundation of successes such as Magicka, Terraria and Space Engineers, proving that it

students.ceid.upatras.gr