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

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

    无前置教程待完成。

     

    本教程适合的人群:

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

     

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

     

     

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

     

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

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

     

     

     

     

    3步:

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

     

     

    4步:

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

     

    ▼代码开始
        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)如下:

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

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

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

    注意到这里有一张纹理图片叫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内容;)

    11步:

     

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

     

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

  • 相关阅读:
    Centos7安装Redis-单节点
    解决物理机U盘安装Kali Linux2018.1,光驱无法加载问题
    做销售如何跟单,逼单!共20招!(转)
    销售沟通技巧(转)
    rails gem (2015-07-16)
    Foundation
    Redis TTL 为0
    Introspection反射机制
    will_paginate
    Linux下Rsync+Inotify-tools实现数据实时同步
  • 原文地址:https://www.cnblogs.com/JackSamuel/p/7277865.html
Copyright © 2011-2022 走看看