当前位置:网站首页>Quick start of UI component development of phantom engine [umg/slate]
Quick start of UI component development of phantom engine [umg/slate]
2022-07-05 03:28:00 【Brain in new VAT】
Unreal Of UMG Provides quite a number of UI Widget, And allow you to do many things in the blueprint . however , Sometimes you may still need to create customizations Widget To fill in the blanks . In this article, we will introduce how to use custom rendering to create Slate Widget Basic knowledge of .
UMG Widget Two classes are involved :
- One UWidget Derived class , You can interact with it in the editor
- One SCompoundWidget class , Deal with low-level functions and rendering
Let's see a simple example of slicing UMG Widget, It has a given starting angle and arc size . We can control the color and opacity , And you can choose to use the image to render it :
1、 Minimum UMG Widget class
First , We will add classes without any functionality , And make sure we see the new widget appear in the editor panel .
This is a UMG Minimize header file for widget :
UCLASS()
class CUSTOMWIDGET_API USlice : public UWidget
{
GENERATED_BODY()
public:
virtual void ReleaseSlateResources(bool bReleaseChildren) override;
protected:
virtual TSharedRef<SWidget> RebuildWidget() override;
TSharedPtr<SSlateSlice> MySlice;
};
Corresponding CPP The documents are as follows :
void USlice::ReleaseSlateResources(bool bReleaseChildren)
{
MySlice.Reset();
}
TSharedRef<SWidget> USlice::RebuildWidget()
{
MySlice = SNew(SSlateSlice);
return MySlice.ToSharedRef();
}
Please note that , Creating a new UMG Widget when , These two methods must always be implemented - RebuildWidget Responsible for building Slate Widget, ReleaseSlateResources Responsible for cleaning up resources .
2、 Minimum Slate Widget class
This is a UMG Widget Class referenced Slate class :
class CUSTOMWIDGET_API SSlateSlice : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SSlateSlice)
{}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
};
And corresponding CPP file :
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SSlateSlice::Construct(const FArguments& InArgs)
{
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION and END_SLATE_FUNCTION_BUILD_OPTIMIZATION Often in Construct Use around functions , Because it may eventually produce a very complex expression , The compiler may spend a lot of time trying to optimize . These macros close and turn optimization on again .
3、 Pass on Widget attribute
To make our UMG Widget Draw slice , You need to add some attributes to determine its appearance . First , We will Brush、Angle and ArcSize Add to UMG Widget:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Appearance")
FSlateBrush Brush;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Appearance")
float Angle;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Appearance")
float ArcSize;
We still need to Slate Class . They are all added as parameters to SLATE_BEGIN_ARGS / SLATE_END_ARGS In macro , And the regular member variables in the class :
SLATE_BEGIN_ARGS(SSlateSlice)
{}
SLATE_ARGUMENT(FSlateBrush*, Brush)
SLATE_ARGUMENT(float, Angle)
SLATE_ARGUMENT(float, ArcSize)
SLATE_END_ARGS()
...
protected:
FInvalidatableBrushAttribute Brush;
float Angle;
float ArcSize;
RebuildWidget Method needs to change these attributes from UMG Widget Pass to Slate Widget:
TSharedRef<SWidget> USlice::RebuildWidget()
{
MySlice = SNew(SSlateSlice)
.Brush(&Brush)
.Angle(Angle)
.ArcSize(ArcSize);
return MySlice.ToSharedRef();
}
Slate Widget Now treat these attributes as Construct Method :
void SSlateSlice::Construct(const FArguments& InArgs)
{
Brush = FInvalidatableBrushAttribute(InArgs._Brush);
Angle = InArgs._Angle;
ArcSize = InArgs._ArcSize;
}
Each defined in the class header SLATE_ARGUMENT Add as a member to FArguments In structure , And underline its name .Construct Method just copies these values into class member variables , For later rendering Widget When using them .
4、Widget Rendering
Now we can finally add OnPaint The method , It deals with Widget The actual rendering of .
At this point , I won't go into details on all the parameters - Here are the parameters we refer to in the following methods :
- AllottedGeometry For us Widget Location and size of
- OutDrawElements Receive for rendering Widget Drawing elements of
- nWidgetStyle It provides us with the color and opacity that should be applied
FSlateDrawElement It's rendering Slate Widget Main force . It has a draw box 、 Line 、 Text 、 Spline, etc . We will use vertices here ( stay 2D In the space ) And index to render arbitrary meshes .
We need to fill the vertices FSlateVertex Structural TArray, And defining a triangle constructed from vertices SlateIndex (uint32) Index value TArray.
To render slices , We add a vertex in the center , Then add edge vertices along the arc . Then the index buffer uses the center and a pair of continuous edge vertices to define the triangle . The color of each vertex is calculated by modulating the brush color using the color and opacity passed in through the widget style and the overall color and opacity of the widget .
If the brush uses an image , We can also set for vertices UV coordinate —— I won't consider it for the time being .
int32 SSlateSlice::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle,
bool bParentEnabled) const
{
const FVector2D Pos = AllottedGeometry.GetAbsolutePosition();
const FVector2D Size = AllottedGeometry.GetAbsoluteSize();
const FVector2D Center = Pos + 0.5 * Size;
const float Radius = FMath::Min(Size.X, Size.Y) * 0.5f;
const FSlateBrush* SlateBrush = Brush.GetImage().Get();
FLinearColor LinearColor = ColorAndOpacity.Get() * InWidgetStyle.GetColorAndOpacityTint() * SlateBrush->GetTint(InWidgetStyle);
FColor FinalColorAndOpacity = LinearColor.ToFColor(true);
const int NumSegments = FMath::RoundToInt(ArcSize / 10.0f);
TArray<FSlateVertex> Vertices;
Vertices.Reserve(NumSegments + 3);
// Add center vertex
Vertices.AddZeroed();
FSlateVertex& CenterVertex = Vertices.Last();
CenterVertex.Position = Center;
CenterVertex.Color = FinalColorAndOpacity;
// Add edge vertices
for (int i = 0; i < NumSegments + 2; ++i)
{
const float CurrentAngle = FMath::DegreesToRadians(ArcSize * i / NumSegments + Angle);
const FVector2D EdgeDirection(FMath::Cos(CurrentAngle), FMath::Sin(CurrentAngle));
const FVector2D OuterEdge(Radius*EdgeDirection);
Vertices.AddZeroed();
FSlateVertex& OuterVert = Vertices.Last();
OuterVert.Position = Center + OuterEdge;
OuterVert.Color = FinalColorAndOpacity;
}
TArray<SlateIndex> Indices;
for (int i = 0; i < NumSegments; ++i)
{
Indices.Add(0);
Indices.Add(i);
Indices.Add(i + 1);
}
const FSlateResourceHandle Handle = FSlateApplication::Get().GetRenderer()->GetResourceHandle( *SlateBrush );
FSlateDrawElement::MakeCustomVerts(
OutDrawElements,
LayerId,
Handle,
Vertices,
Indices,
nullptr,
0,
0
);
return LayerId;
}
This allows us to render slices in different sizes and colors :
5、 to update Widget attribute
In order for the editor to work properly , We need to be in Slate The properties in the widget are UMG Update widgets as they change . We rewrite SynchronizeProperties Function to do this :
void USlice::SynchronizeProperties()
{
Super::SynchronizeProperties();
MySlice->SetBrush(&Brush);
MySlice->SetAngle(Angle);
MySlice->SetArcSize(ArcSize);
}
Slate Widgets need the following setter function :
void SSlateSlice::SetBrush(FSlateBrush* InBrush)
{
Brush.SetImage(*this, InBrush);
}
void SSlateSlice::SetAngle(float InAngle)
{
Angle = InAngle;
}
void SSlateSlice::SetArcSize(float InArcSize)
{
ArcSize = InArcSize;
}
Now? , Just change any attribute in the editor , The slice will be updated immediately .
6、 Set up Widget Category
Unless otherwise specified , otherwise Widget stay UMG Designer's Widget The panel displays as unclassified . To set a category , Please add a pair GetPaletteCategory The covering of functions :
#if WITH_EDITOR
const FText USlice::GetPaletteCategory()
{
return LOCTEXT("CustomPaletteCategory", "My custom category!");
}
#endif
7、 follow-up work
The source code involved in this article can be obtained from GitHub library Download .
Be able to communicate with Unreal In the conventional UMG Widget Before comparison , There is still much work to be done . for example , Property does not support animation , Nor does it support attribute binding . I also didn't discuss the mouse event ——UMG( and Slate) All in Widget It's all rectangular , So in irregular shape Widget It takes some skills to handle the mouse correctly .
Implement customization Widget One potential reason for is optimization - for example , Realize a single... That combines multiple element rendering Widget It could be faster - I will discuss this in the near future .
Link to the original text :Slate Widget Development tutorial — BimAnt
边栏推荐
- MySQL winter vacation self-study 2022 11 (9)
- [groovy] string (string injection function | asBoolean | execute | minus)
- el-select,el-option下拉选择框
- Why do some programmers change careers before they are 30?
- Kuboard
- The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
- Smart pointer shared_ PTR and weak_ Difference of PTR
- Easy processing of ten-year futures and stock market data -- Application of tdengine in Tongxinyuan fund
- Necessary fonts for designers
- Acwing game 58 [End]
猜你喜欢
Pat grade a 1119 pre- and post order traversals (30 points)
This + closure + scope interview question
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
Share the newly released web application development framework based on blazor Technology
SPI and IIC communication protocol
Tiny series rendering tutorial
IPv6 experiment
About MySQL database connection exceptions
Flume配置4——自定义MYSQLSource
el-select,el-option下拉选择框
随机推荐
Easy processing of ten-year futures and stock market data -- Application of tdengine in Tongxinyuan fund
Design and implementation of kindergarten management system
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
Ask, does this ADB MySQL support sqlserver?
[groovy] string (string splicing | multi line string)
Cette ADB MySQL prend - elle en charge SQL Server?
About MySQL database connection exceptions
Une question est de savoir si Flink SQL CDC peut définir le parallélisme. Si le parallélisme est supérieur à 1, il y aura un problème d'ordre?
There is a question about whether the parallelism can be set for Flink SQL CDC. If the parallelism is greater than 1, will there be a sequence problem?
Vb+access hotel service management system
Kubernetes - identity and authority authentication
The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
Sqoop installation
Azkaban实战
this+闭包+作用域 面试题
Design and implementation of community hospital information system
Subversive cognition: what does SRE do?
The latest blind box mall, which has been repaired very popular these days, has complete open source operation source code
Idea inheritance relationship
Apache build web host