c++例子 unreal4
2018-05-29 17:29:16 Kingtem 阅读数 1181

介绍

       在UE4中可以使用C++的智能指针,虽然UE4自身已经对UObject及其派生对象有了较好的垃圾回收机制,但开发者还是会遇到使用指针管理对象的时候。我对其使用方法和类型做了一些简单总结。

智能指针的主要类型分为:TSharedPtr, TSharedRef, TWeakPtr, TAutoPtr。

其特性主要总结为几点:

  1. 类似常规C++指针;
  2. 可防止内存溢出;
  3. 有线程安全机制;
  4. 可虚拟化任何对象;
  5. 负载极小,内存占用仅是原生C++指针的两倍。

使用方式

这里主要针对TSharedPtr(共享指针)的使用进行介绍

声明一个测试类为MyClass:

Class MyClass
{
    public:
        int values;
};

分配及初始化:

TSharedPtr<MyClass> emptySharedClass;	//这是一个空的共享指针
TSharedPtr<MyClass> firstSharedObject(new MyClass());	//声明并初始化了一个共享指针

复制指针:

//当复制了一个共享指针,那引用数就会增加
TSharedPtr<MyClass> anotherObject = firstSharedObject;

在内存中检查一个共享指针的引用数:

firstSharedObject.GetSharedReferenceCount();

三种方法解除引用:

firstSharedObject->values;
firstSharedObject.Get()->values;
(*firstSharedObject).values;

检查指针有效性:

firstSharedObject.IsValid()
或者:
firstSharedObject.Get() != nullptr

2015-09-21 10:02:00 shangguanwaner 阅读数 2320

Unreal Engine 4 C++自定义事件

在本文中将介绍如何实现和Actor中的BeginOverlap和EndOverlap相似的事件。

第一步,声明委托类型

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FActorTest, float, fValue);

上面的宏声明委托的类型,我们可以指定有几个参数,OneParams,TwoParams,以此类推。这是一个动态的委托,我们可以在运行时随时增加或者删除通知的函数。

第二步,定义委托

UPROPERTY(BlueprintAssignable, Category = "Game|Test")
    FActorOnTest OnActorTest;

这是一个成员属性,注意一定要是BlueprintAssignable。

第三步,定义蓝图中实现的事件

UFUNCTION(BlueprintImplementableEvent, Category = "EventTest")
        void ReceiveActorTest(float fValue);

这个函数声明成BlueprintImplementableEvent,表示这是一个在蓝图中实现的事件函数,C++代码中不用实现它,在需要的时候直接调用即可。
比如,我在Tick里触发这个事件:

void AMyEventActor::Tick( float DeltaTime )
{
    Super::Tick( DeltaTime );

    ReceiveActorTest(10);
}

第四步,测试

这里写图片描述

2014-06-04 13:20:00 weixin_30492047 阅读数 2

The first three generations of the Unreal Engine included a sandboxed scripting language, UnrealScript, which provided a simple interface for gameplay programming that was shielded from the complexity of the C++ engine.
The scripting approach is very welcoming to new programmers, but eventually it breaks down and becomes an obstacle to innovation and shipping. We experienced this over time as the Unreal Engine grew until finally, in 2011, we moved to a pure C++ architecture. The causative factors were both pervasive and general:
- As an engine and its community grows, there is increasing pressure to expose more of the its native C++ features to the scripting environment. What starts out as a sandbox full of toys eventually grows into a desert of complexity and duplication.
- As the script interface expands, there is a seemingly exponential increase in the cost and complexity of its interoperability or "interop" layer where C++ and script code communicate through a multi-language interface for calling functions and marshaling data. Interop becomes very tricky for advanced data types such as containers where standard scripting-language idioms differ greatly in representation and semantics from their templated C++ counterparts.
- Developers seeking to take advantage of the engine's native C++ features end up dividing their code unnaturally between the script world and the C++ world, with significant development time lost in this Interop Hell.
- Developers need to look at program behavior holistically, but quickly find that script debugging tools and C++ debugging tools are separate and incompatible. Seeing where script code had gone wrong is of little value if you can't trace the C++ that code led to it, and vice-versa.
It is these reasons, ultimately, that led to Epic's move to pure C++. And the benefits are numerous: UE4 is a unified and fully-debuggable code base, freed from Interop Hell and totally open to programmers to study, modify, and extend. There are side-benefits, too, such as increased performance in gameplay code, and ease of integrating other middleware written in C++.
Building Unreal Engine 4 as a unified C++ codebase has been very freeing, giving engine and gameplay programmers enormous flexibility to write code without unnecessary interop barriers.
This isn't to say that C++ is the ideal language for simple gameplay code. It is more complex and more dangerous than UnrealScript, C#, and JavaScript. But that is another way of saying that it's more powerful.
By making peace with complexity and writing code in C++, there is absolutely no limit to what you can accomplish, whether it involves debugging your entire codebase in-context, interfacing to low-level engine systems, modifying them, or talking to the operating system or advanced third-party libraries.

转载于:https://www.cnblogs.com/wubugui/p/3767682.html

2016-10-21 10:31:14 qq_20309931 阅读数 1696
    接触UnrealEngine4大概有快两周了,从安装配置到编辑器的熟悉,再到官方实例的学习以及Blueprint的应用。从UE3的UnrealScript和各种classes到UE4现在的发开方式,昨天大概拟定了一个UE4引擎探究的计划,下周会围绕计划展开研究。

    这几天再看UnrealEngine4的代码,在写代码的过程中有些注意事项跟大家分享一下,也算给自己做个记录"[转载]Unreal4 <wbr

一. 最好不要自己在UnrealEngine4的工程中添加代码文件,尤其是.h文件。因为UE4的UnrealHeaderTool会根据UnrealEngine4的反射机制自动生成一个.generated.h文件(应该是UnrealBuildTool需要注册并做反射用)。添加代码最好是通过编辑器的创建类向导创建。  如图例:

"[转载]Unreal4 <wbr
    如果想用更多的类作为父类的话,可以点击“右上角”显示所有类。这样的话比如我们想做一个管理器类不需要其他逻辑业务功能我们就可以在 显示所有类 中选择一个UObject作为父类喽,配图如下:

"[转载]Unreal4 <wbr
点击”显示所有类”后,如图:

"[转载]Unreal4 <wbr

二. UnrealEngine4的C++代码有套自己的浅规则,如同Unity3D的限制版C#一样。请各位同学们不要忙着抱怨"[转载]Unreal4 <wbr,经过了13多年承载和UnrealScript的经验想必Epic不会自找苦吃把自己开发饭碗搞的很糟糕。目前笔者看到的优点是拥有GC机制,支持Blueprint和编辑器的反射机制,UnrealBuildTool的运行时编译,还有一些自动化生成功能。闲话不多说,来点干货先。

  1. 声明类时需要添加UCLASS()宏,可以带参数用来标示在编辑器中的名称,暴露类别,显示类别,类别构造,API类型,Blueprint类型,配置文件=名称。
例如:

"[转载]Unreal4 <wbr
  2. 声明变量时需要添加UPROPERTY()宏,可以带参数用来标示 在哪里时可见,高级显示类型,属于哪个类别,标签[类似注释]。
例如:
"[转载]Unreal4 <wbr
 3. 在XXXX.h文件中引用其他头文件,请各位同学一定要在把#include “xxx.h” 放到这个XXXX.h文件#include “XXXX.generated.h” 前,不然会报错呦。
例如:
"[转载]Unreal4 <wbr

4. 下周UnrealEngine4就要更新4.1版本了,最近UE4还属于公测版有不少不稳定的地方,当然官方的更新的速度也很快。在目前这个情况下笔者比较建议采用Unity3D脚本开发的程序结构。做一个自己的逻辑模块聚合到自己的GameMode或者WordSettings下。再由自己的逻辑模块去驱动游戏逻辑调用或者驱动UnrealEngine4的其他模块,开发者把大部分精力放在逻辑模块的架构上和引擎功能模块的调度上,不要上来就想去从GamePlay的入口去改引擎底层的逻辑架构。

原因如下:
1). UnrealEngine4引擎目前还不是很健壮,可能会在开发流程和开发模式上做出变动。
2). UnrealEngine4试图把很多精力放在把大家想Blueprints上去引导,大力推动开发者用Blueprints完成游戏开发。游戏逻辑和Blueprints关联很紧密,如果处理不好久有点得不偿失了会浪费大量时间和精力。


预祝大家开发顺利,欢迎随时沟通 互相学习和进步"[转载]Unreal4 <wbr





2016-12-03 14:33:30 qq_20309931 阅读数 3814

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

好记性不如烂笔头啊,还是记录一下!


如果你觉得Unreal Engine里面的控件没有达到你的需求,你需要添加自定控件。


创建Slate控件

如果你还不了解如何创建一个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<float>() )
        , _FillColorAndOpacity( FLinearColor::White )
        , _BorderPadding( FVector2D(1,0) )
        , _BackgroundImage(&FCoreStyle::Get().GetWidgetStyle<FProgressBarStyle>("ProgressBar").BackgroundImage)
        , _IncreaseImage(&FCoreStyle::Get().GetWidgetStyle<FProgressBarStyle>("ProgressBar").FillImage)
        , _DecreaseImage(&FCoreStyle::Get().GetWidgetStyle<FProgressBarStyle>("ProgressBar").FillImage)
        , _FillImage(&FCoreStyle::Get().GetWidgetStyle<FProgressBarStyle>("ProgressBar").FillImage)
        , _MarqueeImage(&FCoreStyle::Get().GetWidgetStyle<FProgressBarStyle>("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<float>, 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 InArgs   A 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<float> > 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<float> > CurrentPercent;
    TAttribute< TOptional<float> > TargetPercent;
    TAttribute< TOptional<float> > 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<FSlateColor> FillColorAndOpacity;

    /** Border Padding */
    TAttribute<FVector2D> BorderPadding;

    /** Value to drive progress bar animation */
    float MarqueeOffset;

    /** Reference to the widgets current active timer */
    TWeakPtr<FActiveTimerHandle> 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<float> > 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<float> > 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<float> TargetPercentFraction = TargetPercent.Get();
    TOptional<float> MiddlePercentFraction = MiddlePercent.Get();
    TOptional<float> CurrentPercentFraction = CurrentPercent.Get();

    if ( TargetPercentFraction.IsSet() && MiddlePercentFraction.IsSet() && CurrentPercentFraction.IsSet() )
    {
        // Get percent value
        float TargetPercentValue = 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<FActiveTimerHandle> 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<float> 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<EProgressBarExFillType::Type> 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

#endif

protected:

    /** Native Slate Widget */
    TSharedPtr<SProgressBarEx> MyProgressBar;

    //~ Begin UWidget Interface
    virtual TSharedRef<SWidget> 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"

/////////////////////////////////////////////////////
// UProgressBarEx

UProgressBarEx::UProgressBarEx(const FObjectInitializer& ObjectInitializer /*= FObjectInitializer::Get()*/)
    : Super(ObjectInitializer)
{
    // SProgressBarEx::FArguments SlateDefaults;
    // WidgetStyle = *SlateDefaults._Style;
    // WidgetStyle = FMenuStyles::Get().GetWidgetStyle<FProgressBarExStyle>("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<float>() : 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<float> > PercentBinding = OPTIONAL_BINDING_CONVERT(float, Percent, TOptional<float>, ConvertFloatToOptionalFloat);
    TAttribute<FSlateColor> 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<float>() : 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<FProgressBarExStyle>();
            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<SWidget> UProgressBarEx::RebuildWidget()
{
    MyProgressBar = SNew(SProgressBarEx)
        .BorderPadding(FVector2D(0.0f, 0.0f));

    return MyProgressBar.ToSharedRef();
}


#if WITH_EDITOR

const 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的控件:

自定义Slate控件

UnrealEngine4C++射线碰撞

博文 来自: shangguanwaner
没有更多推荐了,返回首页