Unreal|Unreal Engine 4 C++ UMG自定义控件


文章目录

  • **Unreal Engine 4 C++ UMG自定义控件**
    • **创建Slate控件**
    • **添加到UMG编辑器中**

Unreal Engine 4 C++ UMG自定义控件 好记性不如烂笔头啊,还是记录一下!
如果你觉得Unreal Engine里面的控件没有达到你的需求,你需要添加自定控件。
创建Slate控件 【Unreal|Unreal Engine 4 C++ UMG自定义控件】如果你还不了解如何创建一个Slate控件,请先阅读:
Unreal Engine 4 C++ Slate 介绍——用C++和Slate创建菜单(一)

Unreal Engine 4 C++ Slate 介绍——用C++和Slate创建菜单(二)

Unreal Engine 4 C++ Slate 介绍——用C++和Slate创建菜单(三)

这里用我自己写的作为参考:
  • SProgressBarEx.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "UI/Slate/ProgressBarExStyle.h"/** *SProgressBarEx Fill Type */ UENUM(BlueprintType) namespace EProgressBarExFillType { enum Type { // will fill up from the left side to the right LeftToRight, // will fill up from the right side to the left side RightToLeft, // will fill up from the center to the outer edges FillFromCenter, // will fill up from the top to the the bottom TopToBottom, // will fill up from the bottom to the the top BottomToTop, }; }/** A progress extend bar widget.*/ class TESTMOBILE_API SProgressBarEx : public SLeafWidget {public: SLATE_BEGIN_ARGS(SProgressBarEx) : _Style( nullptr ) , _BarFillType(EProgressBarExFillType::LeftToRight) , _Percent( TOptional() ) , _FillColorAndOpacity( FLinearColor::White ) , _BorderPadding( FVector2D(1,0) ) , _BackgroundImage(&FCoreStyle::Get().GetWidgetStyle("ProgressBar").BackgroundImage) , _IncreaseImage(&FCoreStyle::Get().GetWidgetStyle("ProgressBar").FillImage) , _DecreaseImage(&FCoreStyle::Get().GetWidgetStyle("ProgressBar").FillImage) , _FillImage(&FCoreStyle::Get().GetWidgetStyle("ProgressBar").FillImage) , _MarqueeImage(&FCoreStyle::Get().GetWidgetStyle("ProgressBar").MarqueeImage) , _RefreshRate(2.0f) {}/** Style used for the progress bar */ SLATE_STYLE_ARGUMENT( FProgressBarExStyle, Style )/** Defines if this progress bar fills Left to right or right to left*/ SLATE_ARGUMENT( EProgressBarExFillType::Type, BarFillType )/** Used to determine the fill position of the progress bar ranging 0..1 */ SLATE_ATTRIBUTE( TOptional, Percent )/** Fill Color and Opacity */ SLATE_ATTRIBUTE( FSlateColor, FillColorAndOpacity )/** Border Padding around fill bar */ SLATE_ATTRIBUTE( FVector2D, BorderPadding )/** The brush to use as the background of the progress bar */ SLATE_ARGUMENT(const FSlateBrush*, BackgroundImage)/** The brush to use as the increase image of the progress bar */ SLATE_ARGUMENT(const FSlateBrush*, IncreaseImage)/** The brush to use as the decrease image of the progress bar */ SLATE_ARGUMENT(const FSlateBrush*, DecreaseImage)/** The brush to use as the fill image */ SLATE_ARGUMENT(const FSlateBrush*, FillImage)/** The brush to use as the marquee image */ SLATE_ARGUMENT(const FSlateBrush*, MarqueeImage)/** Rate at which this widget is ticked when sleeping in seconds */ SLATE_ARGUMENT(float, RefreshRate)SLATE_END_ARGS()/** * Construct the widget * * @param InArgsA declaration from which to construct the widget */ void Construct(const FArguments& InArgs); /** Paint Widget */ virtual int32 OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const override; virtual FVector2D ComputeDesiredSize(float) const override; virtual bool ComputeVolatility() const override; /** See attribute Percent */ void SetPercent(TAttribute< TOptional > InPercent); /** See attribute Style */ void SetStyle(const FProgressBarExStyle* InStyle); /** See attribute BarFillType */ void SetBarFillType(EProgressBarExFillType::Type InBarFillType); /** See attribute SetFillColorAndOpacity */ void SetFillColorAndOpacity(TAttribute< FSlateColor > InFillColorAndOpacity); /** See attribute BorderPadding */ void SetBorderPadding(TAttribute< FVector2D > InBorderPadding); /** See attribute BackgroundImage */ void SetBackgroundImage(const FSlateBrush* InBackgroundImage); /** See attribute IncreaseImage */ void SetIncreaseImage(const FSlateBrush* InIncreaseImage); /** See attribute IncreaseImage */ void SetDecreaseImage(const FSlateBrush* InDecreaseImage); /** See attribute FillImage */ void SetFillImage(const FSlateBrush* InFillImage); /** See attribute MarqueeImage */ void SetMarqueeImage(const FSlateBrush* InMarqueeImage); private:/** Controls the speed at which the widget is ticked when in slate sleep mode */ void SetActiveTimerTickRate(float TickRate); /** Widgets active tick */ EActiveTimerReturnType ActiveTick(double InCurrentTime, float InDeltaTime); /** Gets the current background image. */ const FSlateBrush* GetBackgroundImage() const; /** Gets the current increase image */ const FSlateBrush* GetIncreaseImage() const; /** Gets the current decrease image */ const FSlateBrush* GetDecreaseImage() const; /** Gets the current fill image */ const FSlateBrush* GetFillImage() const; /** Gets the current marquee image */ const FSlateBrush* GetMarqueeImage() const; private:/** The style of the progress bar */ const FProgressBarExStyle* Style; /** The text displayed over the progress bar */ TAttribute< TOptional > CurrentPercent; TAttribute< TOptional > TargetPercent; TAttribute< TOptional > MiddlePercent; /** The fill type for the progress bar */ EProgressBarExFillType::Type BarFillType; /** Background image to use for the progress bar */ const FSlateBrush* BackgroundImage; /** Increase image to use for the progress bar */ const FSlateBrush* IncreaseImage; /** Decrease image to use for the progress bar */ const FSlateBrush* DecreaseImage; /** Foreground image to use for the progress bar */ const FSlateBrush* FillImage; /** Image to use for marquee mode */ const FSlateBrush* MarqueeImage; /** Value to drive progress bar animation */ float SpeedRate; /** Fill Color and Opacity */ TAttribute FillColorAndOpacity; /** Border Padding */ TAttribute BorderPadding; /** Value to drive progress bar animation */ float MarqueeOffset; /** Reference to the widgets current active timer */ TWeakPtr ActiveTimerHandle; /** Rate at which the widget is currently ticked when slate sleep mode is active */ float CurrentTickRate; /** The slowest that this widget can tick when in slate sleep mode */ float MinimumTickRate; };

  • SProgressBarEx.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "TestMobile.h" #include "SProgressBarEx.h"void SProgressBarEx::Construct(const FArguments& InArgs) { check(InArgs._BackgroundImage); check(InArgs._IncreaseImage); check(InArgs._DecreaseImage); check(InArgs._FillImage); check(InArgs._MarqueeImage); MarqueeOffset = 0.0f; Style = InArgs._Style; TAttribute< TOptional > Percent = InArgs._Percent.Get().IsSet() ? InArgs._Percent : 0.5f; SetPercent(Percent); SpeedRate = 30.0f; BarFillType = InArgs._BarFillType; BackgroundImage = InArgs._BackgroundImage; IncreaseImage = InArgs._IncreaseImage; DecreaseImage = InArgs._DecreaseImage; FillImage = InArgs._FillImage; MarqueeImage = InArgs._MarqueeImage; FillColorAndOpacity = InArgs._FillColorAndOpacity; BorderPadding = InArgs._BorderPadding; CurrentTickRate = 0.0f; MinimumTickRate = InArgs._RefreshRate; ActiveTimerHandle = RegisterActiveTimer(CurrentTickRate, FWidgetActiveTimerDelegate::CreateSP(this, &SProgressBarEx::ActiveTick)); }void SProgressBarEx::SetPercent(TAttribute< TOptional > InPercent) { if (!TargetPercent.IdenticalTo(InPercent)) { CurrentPercent = MiddlePercent = TargetPercent = InPercent; Invalidate(EInvalidateWidget::LayoutAndVolatility); } }void SProgressBarEx::SetStyle(const FProgressBarExStyle* InStyle) { Style = InStyle; if (Style == nullptr) { FArguments Defaults; Style = Defaults._Style; }check(Style); Invalidate(EInvalidateWidget::Layout); }void SProgressBarEx::SetBarFillType(EProgressBarExFillType::Type InBarFillType) { BarFillType = InBarFillType; Invalidate(EInvalidateWidget::Layout); }void SProgressBarEx::SetFillColorAndOpacity(TAttribute< FSlateColor > InFillColorAndOpacity) { FillColorAndOpacity = InFillColorAndOpacity; Invalidate(EInvalidateWidget::Layout); }void SProgressBarEx::SetBorderPadding(TAttribute< FVector2D > InBorderPadding) { BorderPadding = InBorderPadding; Invalidate(EInvalidateWidget::Layout); }void SProgressBarEx::SetBackgroundImage(const FSlateBrush* InBackgroundImage) { BackgroundImage = InBackgroundImage; Invalidate(EInvalidateWidget::Layout); }void SProgressBarEx::SetIncreaseImage(const FSlateBrush* InIncreaseImage) { IncreaseImage = InIncreaseImage; Invalidate(EInvalidateWidget::Layout); }void SProgressBarEx::SetDecreaseImage(const FSlateBrush* InDecreaseImage) { DecreaseImage = InDecreaseImage; Invalidate(EInvalidateWidget::Layout); }void SProgressBarEx::SetFillImage(const FSlateBrush* InFillImage) { FillImage = InFillImage; Invalidate(EInvalidateWidget::Layout); }void SProgressBarEx::SetMarqueeImage(const FSlateBrush* InMarqueeImage) { MarqueeImage = InMarqueeImage; Invalidate(EInvalidateWidget::Layout); }const FSlateBrush* SProgressBarEx::GetBackgroundImage() const { return &Style->BackgroundImage ? &Style->BackgroundImage : BackgroundImage; }const FSlateBrush* SProgressBarEx::GetIncreaseImage() const { return &Style->IncreaseImage ? &Style->IncreaseImage : IncreaseImage; }const FSlateBrush* SProgressBarEx::GetDecreaseImage() const { return &Style->DecreaseImage ? &Style->DecreaseImage : DecreaseImage; }const FSlateBrush* SProgressBarEx::GetFillImage() const { return &Style->FillImage ? &Style->FillImage : FillImage; }const FSlateBrush* SProgressBarEx::GetMarqueeImage() const { return &Style->MarqueeImage ? &Style->MarqueeImage : MarqueeImage; }int32 SProgressBarEx::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const { // Used to track the layer ID we will return. int32 RetLayerId = LayerId; bool bEnabled = ShouldBeEnabled( bParentEnabled ); const ESlateDrawEffect::Type DrawEffects = bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect; const FSlateBrush* CurrentFillImage = GetFillImage(); const FLinearColor FillColorAndOpacitySRGB(InWidgetStyle.GetColorAndOpacityTint() * FillColorAndOpacity.Get().GetColor(InWidgetStyle) * CurrentFillImage->GetTint(InWidgetStyle)); const FLinearColor ColorAndOpacitySRGB = InWidgetStyle.GetColorAndOpacityTint(); // Paint inside the border only. // Pre-snap the clipping rect to try and reduce common jitter, since the padding is typically only a single pixel. FSlateRect SnappedClippingRect = FSlateRect(FMath::RoundToInt(MyClippingRect.Left), FMath::RoundToInt(MyClippingRect.Top), FMath::RoundToInt(MyClippingRect.Right), FMath::RoundToInt(MyClippingRect.Bottom)); const FSlateRect ForegroundClippingRect = SnappedClippingRect.InsetBy(FMargin(BorderPadding.Get().X, BorderPadding.Get().Y)); // Paint background image const FSlateBrush* CurrentBackgroundImage = GetBackgroundImage(); FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry(), CurrentBackgroundImage, SnappedClippingRect, DrawEffects, InWidgetStyle.GetColorAndOpacityTint() * CurrentBackgroundImage->GetTint( InWidgetStyle ) ); TOptional TargetPercentFraction = TargetPercent.Get(); TOptional MiddlePercentFraction = MiddlePercent.Get(); TOptional CurrentPercentFraction = CurrentPercent.Get(); if ( TargetPercentFraction.IsSet() && MiddlePercentFraction.IsSet() && CurrentPercentFraction.IsSet() ) { // Get percent value float TargetPercentValue = https://www.it610.com/article/FMath::Clamp(TargetPercentFraction.GetValue(), 0.0f, 1.0f); float MiddlePercentValue = FMath::Clamp(MiddlePercentFraction.GetValue(), 0.0f, 1.0f); float CurrentPercentValue = FMath::Clamp(CurrentPercentFraction.GetValue(), 0.0f, 1.0f); // Get paint order const FSlateBrush* TopBrush; const FSlateBrush* CenterBrush; const FSlateBrush* BottomBrush; float TopValue; float CenterValue; float BottomValue; TopBrush = GetFillImage(); TopValue = MiddlePercentValue; CenterBrush = GetIncreaseImage(); CenterValue = TargetPercentValue; BottomBrush = GetDecreaseImage(); BottomValue = CurrentPercentValue; switch (BarFillType) { case EProgressBarExFillType::RightToLeft: break; case EProgressBarExFillType::FillFromCenter: break; case EProgressBarExFillType::TopToBottom: break; case EProgressBarExFillType::BottomToTop: break; case EProgressBarExFillType::LeftToRight: default: // Draw bottom layer FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale); ClippedAllotedGeometry.Right = ClippedAllotedGeometry.Left + ClippedAllotedGeometry.GetSize().X * BottomValue; FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry( FVector2D::ZeroVector, FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )), BottomBrush, ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry), DrawEffects, FillColorAndOpacitySRGB ); // Draw center layer ClippedAllotedGeometry =FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale); ClippedAllotedGeometry.Right = ClippedAllotedGeometry.Left + ClippedAllotedGeometry.GetSize().X * CenterValue; FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry( FVector2D::ZeroVector, FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )), CenterBrush, ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry), DrawEffects, FillColorAndOpacitySRGB ); // Draw top layer ClippedAllotedGeometry =FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale); ClippedAllotedGeometry.Right = ClippedAllotedGeometry.Left + ClippedAllotedGeometry.GetSize().X * TopValue; FSlateDrawElement::MakeBox( OutDrawElements, RetLayerId++, AllottedGeometry.ToPaintGeometry( FVector2D::ZeroVector, FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )), TopBrush, ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry), DrawEffects, FillColorAndOpacitySRGB ); break; } } else {}return RetLayerId - 1; }FVector2D SProgressBarEx::ComputeDesiredSize(float) const { return GetMarqueeImage()->ImageSize; }bool SProgressBarEx::ComputeVolatility() const { return SLeafWidget::ComputeVolatility() || TargetPercent.IsBound(); }void SProgressBarEx::SetActiveTimerTickRate(float TickRate) { if (CurrentTickRate != TickRate || !ActiveTimerHandle.IsValid()) { CurrentTickRate = TickRate; TSharedPtr SharedActiveTimerHandle = ActiveTimerHandle.Pin(); if (SharedActiveTimerHandle.IsValid()) { UnRegisterActiveTimer(SharedActiveTimerHandle.ToSharedRef()); }ActiveTimerHandle = RegisterActiveTimer(TickRate, FWidgetActiveTimerDelegate::CreateSP(this, &SProgressBarEx::ActiveTick)); } }EActiveTimerReturnType SProgressBarEx::ActiveTick(double InCurrentTime, float InDeltaTime) { MarqueeOffset = InCurrentTime - FMath::FloorToDouble(InCurrentTime); TOptional TargetPercentFraction = TargetPercent.Get(); if (TargetPercentFraction.IsSet()) { SetActiveTimerTickRate(MinimumTickRate); } else { SetActiveTimerTickRate(0.0f); }return EActiveTimerReturnType::Continue; }

这个是一个多层进度条的Slate控件,紧接着要为他写个Slate样式。
  • ProgressBarExStyle.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "SlateWidgetStyleContainerBase.h" #include "SlateWidgetStyle.h" #include "SlateBasics.h" #include "ProgressBarExStyle.generated.h"/** * Represents the appearance of an SProgressBarEx */ USTRUCT(BlueprintType) struct TESTMOBILE_API FProgressBarExStyle : public FSlateWidgetStyle { GENERATED_USTRUCT_BODY()FProgressBarExStyle(); virtual ~FProgressBarExStyle() {}virtual void GetResources( TArray< const FSlateBrush* >& OutBrushes ) const override; static const FName TypeName; virtual const FName GetTypeName() const override { return TypeName; }; static const FProgressBarExStyle& GetDefault(); /** Background image to use for the progress bar */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Appearance) FSlateBrush BackgroundImage; FProgressBarExStyle& SetBackgroundImage( const FSlateBrush& InBackgroundImage ){ BackgroundImage = InBackgroundImage; return *this; }/** Increase image to use for the progress bar */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Appearance) FSlateBrush IncreaseImage; FProgressBarExStyle& SetIncreaseImage( const FSlateBrush& InIncreaseImage ){ IncreaseImage = InIncreaseImage; return *this; }/** Decrease image to use for the progress bar */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Appearance) FSlateBrush DecreaseImage; FProgressBarExStyle& SetDecreaseImage( const FSlateBrush& InDecreaseImage ){ DecreaseImage = InDecreaseImage; return *this; }/** Foreground image to use for the progress bar */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Appearance) FSlateBrush FillImage; FProgressBarExStyle& SetFillImage( const FSlateBrush& InFillImage ){ FillImage = InFillImage; return *this; }/** Image to use for marquee mode */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Appearance) FSlateBrush MarqueeImage; FProgressBarExStyle& SetMarqueeImage( const FSlateBrush& InMarqueeImage ){ MarqueeImage = InMarqueeImage; return *this; } };

  • ProgressBarExStyle.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "TestMobile.h" #include "ProgressBarExStyle.h"FProgressBarExStyle::FProgressBarExStyle() { }void FProgressBarExStyle::GetResources( TArray< const FSlateBrush* >& OutBrushes ) const { OutBrushes.Add( &BackgroundImage ); OutBrushes.Add( &IncreaseImage ); OutBrushes.Add( &DecreaseImage ); OutBrushes.Add( &FillImage ); OutBrushes.Add( &MarqueeImage ); }const FName FProgressBarExStyle::TypeName( TEXT("FProgressBarExStyle") ); const FProgressBarExStyle& FProgressBarExStyle::GetDefault() { static FProgressBarExStyle Default; return Default; }

到此我们就结束了Slate控件的编写,只是写了个基本的多层进度条。
添加到UMG编辑器中 首先需要给样式加上一个基础容器,并且要反射给UMG的编辑器
  • ProgressExWidgetStyle.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "Styling/SlateWidgetStyleContainerBase.h" #include "UI/Slate/ProgressBarExStyle.h" #include "ProgressExWidgetStyle.generated.h"/** * */ UCLASS(BlueprintType, hidecategories=Object, MinimalAPI) class UProgressExWidgetStyle : public USlateWidgetStyleContainerBase { GENERATED_BODY()public:/** The actual data describing the button's appearance. */ UPROPERTY(Category="Style", EditAnywhere, BlueprintReadWrite, meta=(ShowOnlyInnerProperties)) FProgressBarExStyle ProgressBarExStyle; virtual const struct FSlateWidgetStyle* const GetStyle() const override { return static_cast< const struct FSlateWidgetStyle* >( &ProgressBarExStyle ); } };

然后要让编辑器能看到我们的Slate控件:
  • ProgressBarEx.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "Widget.h" #include "ProgressExWidgetStyle.h" #include "UI/Slate/SProgressBarEx.h" #include "ProgressBarEx.generated.h"class USlateBrushAsset; /** *ProgressBarEx */ UCLASS() class TESTMOBILE_API UProgressBarEx : public UWidget { GENERATED_BODY()public:/** The progress bar ex default setting */ UProgressBarEx(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); /** The progress bar ex style */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Style", meta=( DisplayName="Style" )) FProgressBarExStyle WidgetStyle; /** Style used for the progress bar */ UPROPERTY() USlateWidgetStyleAsset* Style_DEPRECATED; /** The brush to use as the background of the progress bar */ UPROPERTY() USlateBrushAsset* BackgroundImage_DEPRECATED; /** The brush to use as the increase image of the progress bar */ UPROPERTY() USlateBrushAsset* IncreaseImage_DEPRECATED; /** The brush to use as the decrease image of the progress bar */ UPROPERTY() USlateBrushAsset* DecreaseImage_DEPRECATED; /** The brush to use as the fill image */ UPROPERTY() USlateBrushAsset* FillImage_DEPRECATED; /** The brush to use as the marquee image */ UPROPERTY() USlateBrushAsset* MarqueeImage_DEPRECATED; /** Used to determine the fill position of the progress bar ranging 0..1 */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Progress, meta=( UIMin = "0", UIMax = "1" )) float Percent; /** Defines if this progress bar fills Left to right or right to left */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Progress) TEnumAsByte BarFillType; UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Progress) bool bIsMarquee; /** A bindable delegate to allow logic to drive the text of the widget */ UPROPERTY() FGetFloat PercentDelegate; /** Fill Color and Opacity */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Appearance) FLinearColor FillColorAndOpacity; /** */ UPROPERTY() FGetLinearColor FillColorAndOpacityDelegate; public:/** Sets the current value of the ProgressBar. */ UFUNCTION(BlueprintCallable, Category="Progress") void SetPercent(float InPercent); /** Sets the fill color of the progress bar. */ UFUNCTION(BlueprintCallable, Category="Progress") void SetFillColorAndOpacity(FLinearColor InColor); /** Sets the progress bar to show as a marquee. */ UFUNCTION(BlueprintCallable, Category="Progress") void SetIsMarquee(bool InbIsMarquee); //TODO UMG Add Set BarFillType.public://~ Begin UWidget Interface virtual void SynchronizeProperties() override; //~ End UWidget Interface//~ Begin UVisual Interface virtual void ReleaseSlateResources(bool bReleaseChildren) override; //~ End UVisual Interface//~ Begin UObject Interface virtual void PostLoad() override; //~ End UObject Interface#if WITH_EDITOR//~ Begin UWidget Interface virtual const FText GetPaletteCategory() override; virtual void OnCreationFromPalette() override; //~ End UWidget Interface#endifprotected:/** Native Slate Widget */ TSharedPtr> MyProgressBar; //~ Begin UWidget Interface virtual TSharedRef> RebuildWidget() override; //~ End UWidget Interface };

  • ProgressBarEx.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include "TestMobile.h" #include "UMG.h" #include "UMGStyle.h" #include "Slate/SlateBrushAsset.h" #include "ProgressBarEx.h"#define LOCTEXT_NAMESPACE "UMG"/ // UProgressBarExUProgressBarEx::UProgressBarEx(const FObjectInitializer& ObjectInitializer /*= FObjectInitializer::Get()*/) : Super(ObjectInitializer) { // SProgressBarEx::FArguments SlateDefaults; // WidgetStyle = *SlateDefaults._Style; // WidgetStyle = FMenuStyles::Get().GetWidgetStyle("HPBarStyle"); // WidgetStyle.FillImage.TintColor = FLinearColor::White; BarFillType = EProgressBarExFillType::LeftToRight; bIsMarquee = false; Percent = 0; FillColorAndOpacity = FLinearColor::White; }void UProgressBarEx::SetIsMarquee(bool InbIsMarquee) { bIsMarquee = InbIsMarquee; if ( MyProgressBar.IsValid() ) { MyProgressBar->SetPercent(bIsMarquee ? TOptional() : Percent); } }void UProgressBarEx::SetFillColorAndOpacity(FLinearColor Color) { FillColorAndOpacity = Color; if (MyProgressBar.IsValid()) { MyProgressBar->SetFillColorAndOpacity(FillColorAndOpacity); } }void UProgressBarEx::SetPercent(float InPercent) { Percent = InPercent; if ( MyProgressBar.IsValid() ) { MyProgressBar->SetPercent(InPercent); } }void UProgressBarEx::SynchronizeProperties() { Super::SynchronizeProperties(); TAttribute< TOptional > PercentBinding = OPTIONAL_BINDING_CONVERT(float, Percent, TOptional, ConvertFloatToOptionalFloat); TAttribute FillColorAndOpacityBinding = OPTIONAL_BINDING(FSlateColor, FillColorAndOpacity); // MyProgressBar->SetStyle(&WidgetStyle); SProgressBarEx::FArguments SlateDefaults; MyProgressBar->SetBackgroundImage(SlateDefaults._BackgroundImage); MyProgressBar->SetIncreaseImage(SlateDefaults._IncreaseImage); MyProgressBar->SetDecreaseImage(SlateDefaults._DecreaseImage); MyProgressBar->SetFillImage(SlateDefaults._FillImage); MyProgressBar->SetMarqueeImage(SlateDefaults._MarqueeImage); MyProgressBar->SetStyle(&WidgetStyle); MyProgressBar->SetBarFillType(BarFillType); MyProgressBar->SetPercent(bIsMarquee ? TOptional() : PercentBinding); MyProgressBar->SetFillColorAndOpacity(FillColorAndOpacityBinding); }void UProgressBarEx::PostLoad() { Super::PostLoad(); if ( GetLinkerUE4Version() < VER_UE4_DEPRECATE_UMG_STYLE_ASSETS ) { if ( Style_DEPRECATED != nullptr ) { const FProgressBarExStyle* StylePtr = Style_DEPRECATED->GetStyle(); if ( StylePtr != nullptr ) { WidgetStyle = *StylePtr; }Style_DEPRECATED = nullptr; }if ( BackgroundImage_DEPRECATED != nullptr ) { WidgetStyle.BackgroundImage = BackgroundImage_DEPRECATED->Brush; BackgroundImage_DEPRECATED = nullptr; }if ( IncreaseImage_DEPRECATED != nullptr ) { WidgetStyle.IncreaseImage = IncreaseImage_DEPRECATED->Brush; IncreaseImage_DEPRECATED = nullptr; }if ( DecreaseImage_DEPRECATED != nullptr ) { WidgetStyle.DecreaseImage = DecreaseImage_DEPRECATED->Brush; DecreaseImage_DEPRECATED = nullptr; }if ( FillImage_DEPRECATED != nullptr ) { WidgetStyle.FillImage = FillImage_DEPRECATED->Brush; FillImage_DEPRECATED = nullptr; }if ( MarqueeImage_DEPRECATED != nullptr ) { WidgetStyle.MarqueeImage = MarqueeImage_DEPRECATED->Brush; MarqueeImage_DEPRECATED = nullptr; } } }void UProgressBarEx::ReleaseSlateResources(bool bReleaseChildren) { Super::ReleaseSlateResources(bReleaseChildren); MyProgressBar.Reset(); }TSharedRef> UProgressBarEx::RebuildWidget() { MyProgressBar = SNew(SProgressBarEx) .BorderPadding(FVector2D(0.0f, 0.0f)); return MyProgressBar.ToSharedRef(); }#if WITH_EDITORconst FText UProgressBarEx::GetPaletteCategory() { return LOCTEXT("Common", "Common"); }void UProgressBarEx::OnCreationFromPalette() { FillColorAndOpacity = FLinearColor(0, 0.5f, 1.0f); }#endif/#undef LOCTEXT_NAMESPACE

其中RebuildWidgetSynchronizeProperties函数很重要。
编译代码后,打开UMG的编辑器,你会发现Common组件下多了一个Progress Bar Ex的控件:
Unreal|Unreal Engine 4 C++ UMG自定义控件
文章图片

    推荐阅读