본문 바로가기
Study/Unreal

[Unreal/정리] UI_아이템

by generous_jeans 2020. 11. 10.

[ 배경 UI ]

- 배경 UI 위젯 생성 -

(언리얼 에디터) UI -> 우클릭_유저 인터페이스-위젯 블루프린트 : "UI_MainHUD"

 

(언리얼 에디터-UI_MainHUD) Button : "OptionButton" -> 디테일-변수인지 : "해제"

(언리얼 에디터-UI_MainHUD) Button : "OptionButton" -> 디테일-이미지 설정(0.9 1.0 0.7) DrawAs : "Image" 

 

(언리얼 에디터-UI_MainHUD) Button : "InventoryButton" -> 디테일-변수인지 : "해제" 

(언리얼 에디터-UI_MainHUD) Button : "InventoryButton" -> 디테일-이미지 설정(0.9 1.0 0.7) DrawAs : "Image"

 

(언리얼 에디터-UI_MainHUD) Button : "CharacterStateButton" -> 디테일-변수인지 : "해제" 

(언리얼 에디터-UI_MainHUD) Button : "CharacterStateButton" -> 디테일-이미지 설정(0.9 1.0 0.7) 

 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++클래스 -> 부모 :"UserWidget" 이름 : "MainUHDWidget"

 

(언리얼 에디터-UI_MainHUD부모클래스 : "MainUHDWidget" 

 

(C++-MainUHDWidget.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "Blueprint/UserWidget.h"
#include "MainHUDWidget.generated.h"

UCLASS()
class UE7PROJECT_API UMainHUDWidget : public UUserWidget
{
    GENERATED_BODY()

protected:
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UButton* OptionButton;

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UButton* InventoryButton;

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UButton* CharacterStateButton;

protected:
    virtual void NativePreConstruct();
    virtual void NativeConstruct();
    virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime);

private:
    UFUNCTION(BlueprintCallable)
    void OptionButtonCallback();

    UFUNCTION(BlueprintCallable)
    void InventoryButtonCallback();

    UFUNCTION(BlueprintCallable)
    void CharacterStateButtonCallback();
    
};

(C++-MainUHDWidget.cpp)

// Fill out your copyright notice in the Description page of Project Settings.


#include "MainHUDWidget.h"
#include "Components/Button.h"

void UMainHUDWidget::NativePreConstruct()
{
    Super::NativePreConstruct();

    OptionButton = Cast<UButton>(GetWidgetFromName(TEXT("OptionButton")));
    InventoryButton = Cast<UButton>(GetWidgetFromName(TEXT("InventoryButton")));
    CharacterStateButton = Cast<UButton>(GetWidgetFromName(TEXT("CharacterStateButton")));

    OptionButton->OnClicked.AddDynamic(this, &UMainHUDWidget::OptionButtonCallback);
    InventoryButton->OnClicked.AddDynamic(this, &UMainHUDWidget::InventoryButtonCallback);
    CharacterStateButton->OnClicked.AddDynamic(this, &UMainHUDWidget::CharacterStateButtonCallback);
}

void UMainHUDWidget::NativeConstruct()
{
    Super::NativeConstruct();
}

void UMainHUDWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
    Super::NativeTick(MyGeometry, InDeltaTime);
}

void UMainHUDWidget::OptionButtonCallback()
{
}

void UMainHUDWidget::InventoryButtonCallback()
{
}

void UMainHUDWidget::CharacterStateButtonCallback()
{
}

(C++-MainGameMode.h) 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "GameFramework/GameModeBase.h"
#include "MainGameMode.generated.h"

/**
 * 
 */
UCLASS()
class UE7PROJECT_API AMainGameMode : public AGameModeBase
{
    GENERATED_BODY()

public:
    AMainGameMode();

private:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    TSubclassOf<UUserWidget> MainHUDWidgetClass;


    UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UMainHUDWidget* MainHUDWidget;

public:
    virtual void BeginPlay();
    
};

(C++-MainGameMode.cpp)

// Fill out your copyright notice in the Description page of Project Settings.


#include "MainGameMode.h"
#include "Wukong.h"
#include "WukongController.h"
#include "UE7GameInstance.h"
#include "MainHUDWidget.h"

AMainGameMode::AMainGameMode()
{
    static ConstructorHelpers::FClassFinder<UUserWidget> MainHUDWidgetAsset(TEXT("WidgetBlueprint'/Game/UI/UI_MainHUD.UI_MainHUD_C'"));

    if (MainHUDWidgetAsset.Succeeded())
        MainHUDWidgetClass = MainHUDWidgetAsset.Class;
}    

void AMainGameMode::BeginPlay()
{
    Super::BeginPlay();

    if (IsValid(MainHUDWidgetClass))
    {
        MainHUDWidget = Cast<UMainHUDWidget>(CreateWidget(GetWorld(), MainHUDWidgetClass));

        if (MainHUDWidget)
        {
            MainHUDWidget->AddToViewport();
        }
    }
}

 

- 리스트 뷰 - 

그리디 형태 인벤토리 / 목록 형태 인벤토리

리스트뷰를 만들기 위해서는 UMG가 2개 필요 : 보여질 것과 그 안의 목록

 

(언리얼 에디터) UI -> 우클릭_유저 인터페이스-위젯 블루프린트 -> "UI_Inventory"

(언리얼 에디터) UI -> 우클릭_유저 인터페이스-위젯 블루프린트 -> "UI_InventoryItem"

 

(언리얼 에디터) UI -> 우클릭_블루프린트 클래스 -> 부모 : "UObject" 이름 : "UI_InentoryItemData"

 

(언리얼 에디터-UI_Inventory) Custom 너비 : "300" 하이트 : "500"

 

(언리얼 에디터-UI_Inventory) 리스트-List View 배치

 

(언리얼 에디터-UI_Inventory) 디테일-List View-Orientation : "Vertical"  // 스트롤을 가로로 할 것인지 세로로 할 것인지. 

(언리얼 에디터-UI_Inventory) 디테일-List View-Selection Mode : "Single"  // 선택을 어떻게 할 것인지. 

(언리얼 에디터-UI_Inventory) 디테일-List View-Consume Mouse Wheel : "When Scrolling Possible" // 마우스의 휠로 스크롤이 가능하게 함. 

 

- 아이템 설정 - 

(언리얼 에디터) C++클래스 -> 우클릭_새 C++클래스 -> 부모 : "User Widget" 이름 : "Inventory"

(언리얼 에디터) C++클래스 -> 우클릭_새 C++클래스 -> 부모 : "User Widget" 이름 : "InventoryItem"

(언리얼 에디터) C++클래스 -> 우클릭_새 C++클래스 -> 부모 : "Object" 이름 : "InventoryItemData"

 

(언리얼 에디터-UI_Inventory) 부모클래스 : "Inventory"

(언리얼 에디터-UI_InventoryItem) 부모클래스 : "InventoryItem

 

(언리얼 에디터-UI_InentoryItemData) 부모클래스 : "InventoryItemData"

 

- 아이템 설정 - 

(언리얼 에디터-UI_InventoryItem) 그래프 -> 디테일-인터페이스-구현된 인터페이스 추가 : "User Object List Entry"

// 리스트뷰의 목록으로 들어갈 때 이것을 설정해줘야 인식을 해서 사용할 수 있음. 

 

(언리얼 에디터-UI_InventoryItem) 이벤트 그래프 

 

(언리얼 에디터-UI_Inventory) List View -> 디테일-List Entries-Entry Widget Class : "UI_InventoryItem"  // 아이템 클래스로 무엇을 쓸 것인지. 

(언리얼 에디터-UI_Inventory) List View : " InventoryList"

(언리얼 에디터-UI_Inventory) Image : "Back"

 

(언리얼 에디터-UI_Inventory) Back -> 이미지 설정 

 

(언리얼 에디터-UI_InventoryItem) 너비 : "290" 하이트 : "80"

 

(언리얼 에디터-UI_Inventory) InventoryList -> 디테일-List Entries-Entry Spacing : "10" 

(언리얼 에디터-UI_Inventory) InventoryList -> 디테일-List Entries- "20"

 

(언리얼 에디터-UI_Inventory) InventoryList -> 디테일-Scrolling-Enable Scroll Animation"체크"

 

(언리얼 에디터-UI_InventoryItem) Image : "Back" -> 이미지 설정

(언리얼 에디터-UI_InventoryItem) Image : "Icon" -> 변수인지 : "해제" 이미지 설정

(언리얼 에디터-UI_InventoryItem) Text : "Name" -> 텍스트 설정 

(언리얼 에디터-UI_InventoryItem) Text : "Count" -> 텍스트 설정 

 

(언리얼 에디터-UI_Inventory) Text : "TitleName" -> 텍스트 설정 

 

(C++-InventoryItemData.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "UObject/NoExportTypes.h"
#include "InventoryItemData.generated.h"

UCLASS(Blueprintable, BlueprintType)
class UE7PROJECT_API UInventoryItemData : public UObject
{
    GENERATED_BODY()
	
protected:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    int32 Index;  // 현재 몇 번째 인덱스 인지.
 
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    int32 ItemNumber;  // 아이템 번호.

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    int32 ItemCount;  //아이템 갯수.
    
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    FString strName;  // 이름.

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    UTexture2D* IconTexture;  // 사용하는 텍스쳐.

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Meta = (AllowPrivateAccess = "true"))
    FString strMeshPath;  // 아이템을 장착하는 경우 어떤 메쉬인지 알아야 하기 때문에 선언.

public:  // 정보를 얻어오기 위해. 
    int32 GetIndex() const
    {
        return Index;
    }

    int32 GetItemNumber() const
    {
        return ItemNumber;
    }

    int32 GetItemCount() const
    {
        return ItemCount;
    }

    FString GetItemName() const
    {
        return strName;
    }

    FString GetMeshPath() const
    {
        return strMeshPath;
    }

    UTexture2D* GetIconTexture() const
    {
        return IconTexture;
    }

public:  // 정보를 설정하기 위해.
    void SetItemIndex(int32 idx)
    {
        Index = idx;
    }

    void SetItemCount(int32 Count)
    {
        ItemCount = Count;
    }

    void SetItemName(const FString& Name)
    {
        strName = Name;
    }

    void SetIconTexture(const FString& strPath)
    {
        IconTexture = LoadObject<UTexture2D>(nullptr, *strPath);
    }

    void SetIconTexture(UTexture2D* pTex)
    {
        IconTexture = pTex;
    }

    void SetMeshPath(const FString& strPath)
    {
        strMeshPath = strPath;
    }
};

 

(C++-InventoryItem.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "Blueprint/UserWidget.h"
#include "InventoryItem.generated.h"

/**
 * 
 */
UCLASS()
class UE7PROJECT_API UInventoryItem : public UUserWidget
{
    GENERATED_BODY()

protected:
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UTextBlock* NameText;

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UTextBlock* CountText;

    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UImage* IconImage;

    int32 Index;
    int32 ItemCount;

protected:
    virtual void NativeConstruct();
    virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime);

public:
    void SetItemIndex(int32 idx)
    {
        Index = idx;
    }

    void SetItemCount(int32 Count);
    void SetItemName(const FString& strName);
    void SetIconTexture(const FString& strPath);
    void SetIconTexture(UTexture2D* pTex);

public:
    UFUNCTION(BlueprintCallable)
    void SetData(class UInventoryItemData* Data);

};

(C++-InventoryItem.cpp)

// Fill out your copyright notice in the Description page of Project Settings.


#include "InventoryItem.h"
#include "Components/TextBlock.h"
#include "Components/Image.h"
#include "InventoryItemData.h"

void UInventoryItem::NativeConstruct()
{
    Super::NativeConstruct();

    NameText = Cast<UTextBlock>(GetWidgetFromName(TEXT("Name")));
    CountText = Cast<UTextBlock>(GetWidgetFromName(TEXT("Count")));
    IconImage = Cast<UImage>(GetWidgetFromName(TEXT("Icon")));
}

void UInventoryItem::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
    Super::NativeTick(MyGeometry, InDeltaTime);
}

void UInventoryItem::SetItemCount(int32 Count)
{
    ItemCount = Count;

    FString strText;
    strText = FString::Printf(TEXT("%d"), ItemCount);
    
    CountText->SetText(FText::FromString(strText));
}

void UInventoryItem::SetItemName(const FString& strName)
{
    CountText->SetText(FText::FromString(strName));
}

void UInventoryItem::SetIconTexture(const FString& strPath)
{
    UTexture2D* IconTex = LoadObject<UTexture2D>(nullptr, *strPath);

    IconImage->SetBrushFromTexture(IconTex);
}

void UInventoryItem::SetIconTexture(UTexture2D* pTex)
{
    IconImage->SetBrushFromTexture(pTex);
}

void UInventoryItem::SetData(class UInventoryItemData* Data)
{
    Index = Data->GetIndex();
    SetItemCount(Data->GetItemCount());
    SetItemName(Data->GetItemName());
    SetIconTexture(Data->GetIconTexture());
}

(C++-Inventory.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "Blueprint/UserWidget.h"
#include "Inventory.generated.h"

/**
 * 
 */
UCLASS()
class UE7PROJECT_API UInventory : public UUserWidget
{
    GENERATED_BODY()

protected:
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
    class UListView* List;

protected:
    virtual void NativeConstruct();
    virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime);

public:
    UFUNCTION(BlueprintCallable)
    void InitList();

    UFUNCTION(BlueprintCallable)
    void ItemClick(UObject* Obj);
};

(C++-Inventory.cpp)

// Fill out your copyright notice in the Description page of Project Settings.


#include "Inventory.h"
#include "Components/ListView.h"
#include "InventoryItemData.h"
#include "WukongController.h"
#include "PlayerCharacter.h"

void UInventory::NativeConstruct()
{
    Super::NativeConstruct();

    List = Cast<UListView>(GetWidgetFromName(TEXT("InventoryList")));

    List->OnItemClicked().AddUObject(this, &UInventory::ItemClick);

    InitList();
}

void UInventory::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
    Super::NativeTick(MyGeometry, InDeltaTime);
}

void UInventory::InitList()  // 리스트 생성.
{
    for (int32 i = 0; i < 2000; ++i)  // 2000개 생성. 
    {
        UInventoryItemData* Data = NewObject<UInventoryItemData>(this, UInventoryItemData::StaticClass());

        Data->SetItemIndex(i);
        Data->SetItemCount(1);
		
        switch (FMath::RandRange(0, 2))  // 아이템 3종류 생성.
        {
        case 0:
            Data->SetItemName(TEXT("Weapon1"));
            Data->SetIconTexture(TEXT("Texture2D'/Game/UI/T_UI_Weapon_Sword.T_UI_Weapon_Sword'"));
            Data->SetMeshPath(TEXT("SkeletalMesh'/Game/InfinityBladeWeapons/Weapons/Blade/Swords/Blade_BlackKnight/SK_Blade_BlackKnight.SK_Blade_BlackKnight'"));
           
           break;
        case 1:
            Data->SetItemName(TEXT("Weapon2"));
            Data->SetIconTexture(TEXT("Texture2D'/Game/UI/T_UI_Icon_PotMana01.T_UI_Icon_PotMana01'"));
            Data->SetMeshPath(TEXT("SkeletalMesh'/Game/InfinityBladeWeapons/Weapons/Blunt/Blunt_Primative/SK_Blunt_Primative.SK_Blunt_Primative'"));
            
            break;
        case 2:
            Data->SetItemName(TEXT("Weapon3"));
            Data->SetIconTexture(TEXT("Texture2D'/Game/UI/T_UI_Weapon_Axe.T_UI_Weapon_Axe'"));
            Data->SetMeshPath(TEXT("SkeletalMesh'/Game/InfinityBladeWeapons/Weapons/Dual_Blade/Dual_Blade_SwordOfStorms/SK_Dual_Blade_SwordOfStorms.SK_Dual_Blade_SwordOfStorms'"));
            
            break;
        }

        List->AddItem(Data);
        
        //List->RemoveItem();
    }
}

void UInventory::ItemClick(UObject* Obj)  // 아이템을 클릭했을 때.
{
    PrintViewport(2.f, FColor::Red, TEXT("ItemClick"));

    UInventoryItemData* pData = Cast<UInventoryItemData>(Obj);

    if (IsValid(pData))
    {
        AWukongController* Controller = Cast<AWukongController>(GetWorld()->GetFirstPlayerController());

        if (IsValid(Controller))
        {
            APlayerCharacter* PlayerChar = Cast<APlayerCharacter>(Controller->GetPawn());
        
            if (IsValid(PlayerChar))
                PlayerChar->ChangeWeapon(pData->GetMeshPath());
        }
    }
}

 

(언리얼 에디터-UI_MainHUD) 사용자 생성 : "UI_Inventory" 배치

// 확인하기 위하여 배치. 

 

(언리얼 에디터-UI_InventoryItem) 이벤트 그래프

(언리얼 에디터-UI_Inventory) InventoryList -> 디테일-Clipping : "Cliip to Bounds"

 

(C++PlayerCharacter.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "GameFramework/Character.h"
#include "PlayerCharacter.generated.h"

UCLASS()
class UE7PROJECT_API APlayerCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    // Sets default values for this character's properties
    APlayerCharacter();

protected:
    bool bStartAnimation;

    UPROPERTY(Category = Item, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
    class AWeapon* Weapon;

public:
    void StartAnimation()
    {
        bStartAnimation = true;
    }

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

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

    // Called to bind functionality to input
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

public:
    void ChangeWeapon(const FString& strPath);  // 무기 교체.
    
};

 

(C++PlayerCharacter.cpp)

// Fill out your copyright notice in the Description page of Project Settings.


#include "PlayerCharacter.h"
#include "Weapon.h"

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

    bStartAnimation = false;

    GetMesh()->SetReceivesDecals(false);
}

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

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

}

// Called to bind functionality to input
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

}

void APlayerCharacter::ChangeWeapon(const FString& strPath)  // 무기를 바꿈.
{
    Weapon->LoadMesh(strPath);
    
}

 

 

(언리얼 에디터) 새 폴터 : "Item"

// 필요할 경우 사용. 

 

- 마우스 - 

(언리얼 에디터) 마우스 이미지 -> 입력- : "UserInterface" 

// UI용으로 사용할 경우 UserInterface로 설정하여 사용해야 함. 

 

(C++-WukongController.h)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameInfo.h"
#include "GameFramework/PlayerController.h"
#include "WukongController.generated.h"

/**
 * 
 */
UCLASS()
class UE7PROJECT_API AWukongController : public APlayerController
{
    GENERATED_BODY()

public:
    AWukongController();
    
private:
    TSubclassOf<UUserWidget> MouseWidgetClass;
    UUserWidget* MouseWidget;

private:
    virtual void BeginPlay();
    
};

(C++-WukongController.cpp)

// Fill out your copyright notice in the Description page of Project Settings.


#include "WukongController.h"
#include "Blueprint/UserWidget.h"

AWukongController::AWukongController()
{
    bShowMouseCursor = true;

    static ConstructorHelpers::FClassFinder<UUserWidget> MouseAsset(TEXT("WidgetBlueprint'/Game/UI/UIMouse.UIMouse_C'"));

    if (MouseAsset.Succeeded())
    {
        MouseWidgetClass = MouseAsset.Class;
        LOG(TEXT("Mouse On"));
    }
}

void AWukongController::BeginPlay()
{
    FInputModeGameAndUI	inputMode;
    SetInputMode(inputMode);

    if (IsValid(MouseWidgetClass))
    {
        MouseWidget = CreateWidget(GetWorld(), MouseWidgetClass);

        if (IsValid(MouseWidget))
        {
            // 마우스 애셋 지정
            SetMouseCursorWidget(EMouseCursor::Default, MouseWidget);
            LOG(TEXT("Mouse Complete"));
        }
    }
}

 

/* UI 드래그 앤 드롭 */  검색

 

- 아이템 상자 떨어지는 것 -

(언리얼 에디터) 큐브 배치 -> 디테일 -> 피직스 : 

// 경사가 있는 곳에서 사용할 경우 굴러갈 수 있으므로 주의해야 함. 

// 땅에 부딪힐 때 물리 시뮬레이션을 끄도록 설정하면 됨. 오버랩만 하도록.

 

 

 

댓글