实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

完成本迷你教程之前,请前往完成以下迷你教程:

无前置教程待完成。

本教程适合的人群:

初学者,具有开发经验两周;

本示例的目的:为了在代码中实现UMG中的这个功能:

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

说明:这是一些列迷你教程的首篇,所以步骤比较多。

1步:创建一个FPSC++)模板工程,我的工程命名为LearnWidgets

2步:在c++文件夹中找到以下已有的两个类,LearnWidgetsGameMode派生出BPGMLearnWidgetsHUD派生出BPHUD;并在BPGM中配置HUDBPHUD

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

3步:

创建一个继承自AActor的类,称为WidgetMng,表示Widget的管理者类,它的功能将会慢慢变强大。

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

4步:

工程.build.cs文件中改动代码:

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

▼代码开始
    public LearnWidgets(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay"
//从这一行开始是新增的——————
, "UMG" });

        // Uncomment if you are using Slate UI
        PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
//新增结束——————
    }
▲代码结束

【实验Tips:如果遇到了无法编译的问题,可以尝试关闭Editor,重启VS,后再build

5步:

WidgetMng的代码是这样的:(按照我的风格,我会在代码中写入详细的注释,边看代码边看注释就会明白)

▼代码开始
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"

#include "WidgetMng.generated.h"

UCLASS()
class LEARNWIDGETS_API AWidgetMng : public AActor
{
    GENERATED_BODY()

public:    
    // Sets default values for this actor's properties
    AWidgetMng();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public:    
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Ws)
        TSubclassOf<class UUserWidget> SlaveWidgetClass;
//这是一个UUserWidget的类目(暴露给蓝图以做选择)

    UPROPERTY()
        class UUserWidget* SlaveWidget;
//这是真正的UUserWidget实例的指针(当然起初是null)

    UFUNCTION()
        void Initialize();
//初始化函数

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = WsTexture)
        UTexture2D* T2D;
//这是一张纹理UTexture2D,暴露给蓝图以做选择    

    UFUNCTION()
        void ChangeImage(UTexture2D* T2D0);
//ChangeImage函数希望将它所管理的SlaveWidget中的Image小部件的图片设置为T2D0纹理

    UFUNCTION()
        void ChangeText(const FString & F);
//ChangeText函数希望将它所管理的SlaveWidget中的TextBlock小部件的文本设置为F;

};

▲代码结束
以下是cpp文件。

▼代码开始
// Fill out your copyright notice in the Description page of Project Settings.

#include "WidgetMng.h"
#include "Runtime/UMG/Public/Blueprint/UserWidget.h"
#include "Runtime/UMG/Public/Components/Image.h"
#include "Runtime/Engine/Classes/Engine/Texture2D.h"
#include "Runtime/UMG/Public/Components/TextBlock.h"
//这里要加一些头文件,至于头文件如何加,这里就先不解释了。

// Sets default values
AWidgetMng::AWidgetMng()
{
     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AWidgetMng::BeginPlay()
{
    Super::BeginPlay();

}

// Called every frame
void AWidgetMng::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}

void AWidgetMng::Initialize()
{
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("31 Initialize WidgetMng"));
//这是LOG

    if (SlaveWidgetClass && SlaveWidget==NULL)
    {
        SlaveWidget = CreateWidget<UUserWidget>(GWorld->GetGameInstance(), SlaveWidgetClass);//【重要】创建UUserWidget的做法
        if (SlaveWidget)
        {
            SlaveWidget->AddToViewport();//将此实例加到屏幕上

        }
    }
}

void AWidgetMng::ChangeImage(UTexture2D* T2D0)
{
    UImage* MyImage = Cast<UImage>(SlaveWidget->GetWidgetFromName(TEXT("MyImage")));
//【重要】从SlaveWidget中找到一个名为MyImage的小部件
    if (MyImage)
    {
        UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("Changing Image With A T2D"));
        MyImage->SetBrushFromTexture(T2D0);//【重要】用纹理UTexture2D来设置这个Image小部件
    }

}

void AWidgetMng::ChangeText(const FString & F)
{//【重要】这个函数展示了设置特定文本给一个名为MyTextBlock的小部件;
    UTextBlock* MyTextBlock = Cast<UTextBlock>(SlaveWidget->GetWidgetFromName(TEXT("MyTextBlock")));
    if (MyTextBlock)
    {
        MyTextBlock->SetText(FText::FromString(F));
    }

}

▲代码结束

5+步:在内容浏览器中新建一个UserWidget(命名为WeaponDisplayer)如下:

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

注意到它有两个小部件,我们命名为MyImageMyTextBlock

6步:找到WidgetMngCpp),然后派生一个蓝图名为BPWidgetMng1

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

第7步:给BPWidgetMng1中配置白色框框部分(还记得吗,它们是前面步骤暴露出来的):

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

注意到这里有一张纹理图片叫wenjiezou,你可以import其它的图像文件进来作为纹理;

8步:

前面写完了WidgetMngWidget管理者),现在写HUD的逻辑,希望HUD能够生成WidgetMng;然后再生成UserWidget(也就是SlaveWidget)。(分号后面这句话已经编写完逻辑了,现在要做的就是分号前的那个需求)

LearnWidgetsHUD中,只需要稍微改改代码即可。

LearnWidgetsHUD.h文件:

▼代码开始
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#pragma once 

#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "WidgetMng/WidgetMng.h"
#include "LearnWidgetsHUD.generated.h"

UCLASS()
class ALearnWidgetsHUD : public AHUD
{
    GENERATED_BODY()

public:
    ALearnWidgetsHUD();

    /** Primary draw call for the HUD */
    virtual void DrawHUD() override;

private:
    /** Crosshair asset pointer */
    class UTexture2D* CrosshairTex;

public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = WidgetMngs)
        TArray<TSubclassOf<AWidgetMng>> WidgetMngsClasses;//【暴露了一些Mngs的类目】
    UPROPERTY()
        TArray<AWidgetMng*> WidgetMngs;//真正的Mngs实例

    virtual void BeginPlay() override;
};


▲代码结束

LearnWidgetsHUD.cpp文件:
▼代码开始
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#include "LearnWidgetsHUD.h"
#include "Engine/Canvas.h"
#include "Engine/Texture2D.h"
#include "TextureResource.h"
#include "CanvasItem.h"
#include "UObject/ConstructorHelpers.h"

ALearnWidgetsHUD::ALearnWidgetsHUD()
{
    // Set the crosshair texture
    static ConstructorHelpers::FObjectFinder<UTexture2D> CrosshairTexObj(TEXT("/Game/FirstPerson/Textures/FirstPersonCrosshair"));
    CrosshairTex = CrosshairTexObj.Object;
}


void ALearnWidgetsHUD::DrawHUD()
{
    Super::DrawHUD();

    // Draw very simple crosshair

    // find center of the Canvas
    const FVector2D Center(Canvas->ClipX * 0.5f, Canvas->ClipY * 0.5f);

    // offset by half the texture's dimensions so that the center of the texture aligns with the center of the Canvas
    const FVector2D CrosshairDrawPosition( (Center.X),
                                           (Center.Y + 20.0f));

    // draw the crosshair
    FCanvasTileItem TileItem( CrosshairDrawPosition, CrosshairTex->Resource, FLinearColor::White);
    TileItem.BlendMode = SE_BLEND_Translucent;
    Canvas->DrawItem( TileItem );
}

//只关注这里,这里实例化了WidgetMng
void ALearnWidgetsHUD::BeginPlay()
{
    for (auto index = 0; index<WidgetMngsClasses.Num(); index++)
    {
        AWidgetMng* NewWidgetMng = NewObject<AWidgetMng>(GetGameInstance(), WidgetMngsClasses[index]);
        WidgetMngs.Add(NewWidgetMng);
        NewWidgetMng->Initialize();
    }
}

▲代码结束

9步:现在再介绍一个点,就是从PCplayercontroller)指挥这个Mng修改文字或图片。我发现没有PC,只有现成的LearnWidgetsCharacter,所以这里就介绍从Character索引到WidgetMng,其实都差不多;

LearnWidgetsCharacter中加入代码:

void ALearnWidgetsCharacter::Action1()
{
    UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("Action1 ing"));
    ALearnWidgetsHUD*  HUD = Cast<ALearnWidgetsHUD>(UGameplayStatics::GetPlayerController(this, 0)->GetHUD());//【重要】这是从Character索引到HUD的方法
    if (HUD->WidgetMngs.Num())
    {
        HUD->WidgetMngs[0]->ChangeImage(HUD->WidgetMngs[0]->T2D);//【重要】从HUD索引到WidgetMng,调用显示图像函数
    }
}

然后再讲这个Action1绑定在Action1输入上(如果这个不懂,请学习setupinputcomponent相关的知识);

10步:

Gamemode是这样的。(如果你不知道什么是Gamemode,请去官网学习Gamemode内容;)

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

11步:

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

按下Action1后(这个Action1是你自己定义的按键噢):

实例甜点 Unreal Engine 4迷你教程(1)之如何用C++将纹理绘制在UserWidget的Image小部件上

——小江村儿的文杰 zouwj5@qq.com 20178214:56:24

原文链接: https://www.cnblogs.com/JackSamuel/p/7277865.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/257801

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 上午11:15
下一篇 2023年2月14日 上午11:16

相关推荐