LeeTaes 공부노트

[UE Team Project/T.A.] 8. 아이템 및 인벤토리 - 2 (UI - Slot) 본문

프로젝트/TimelessAdventure

[UE Team Project/T.A.] 8. 아이템 및 인벤토리 - 2 (UI - Slot)

리태s 2024. 10. 10. 17:43
728x90
반응형

개요

이번 포스팅에서는 이전에 만든 인벤토리를 UI에 띄우는 방법에 대해 정리해보도록 하겠습니다.


Slot 구조 및 디자인

Slot은 실제로 상점, 인벤토리, 퀵슬롯에 사용되는 슬롯을 위한 클래스입니다.

 

이전 포스팅에서 제작한 인벤토리나 상점에서 데이터를 가져오기 위해 슬롯은 자신의 Owner를 알아야 하며, 이를 위해 Custom Widget 클래스를 간단히 제작하였습니다.

부모 액터를 저장하기 위핸 Custom Widget

 

Slot 클래스는 Custom Widget 클래스를 상속받았으며, 슬롯의 주인과 타입에 따라 정보를 가져와 반영해줘야 합니다.

 

디자인은 심플하게 배경, 아이템 아이콘, 수량으로만 다음과 같이 구성하였습니다.

 

우선 디자인했던 위젯을 C++에서 바인딩해주고, 추가적인 정보를 선언해주도록 합니다.

 

슬롯의 타입과 인덱스는 인벤토리와 같이 여러 슬롯을 사용하는 경우 해당 슬롯이 어떤 슬롯인지를 판별하기 위해 필수적으로 존재해야 하는 변수이며, 빈 슬롯의 아이콘을 채우기 위한 투명 Texture를 추가하였습니다.

 

또한, 드래그 & 드롭시 생성될 Slot Widget의 클래스를 저장해주도록 하였습니다.


드래그 & 드롭 기능 구현 - DragDropOperation

드래그 & 드롭 기능은 Unreal에서 제공해주는 DragDropOperation 클래스를 사용하여 구현하게 되었습니다.

 

대표적인 기능은 다음과 같습니다.

  • Payload : 드래그하는 동안 전달되는 실제 데이터. 일반적으로 드래그할 아이템에 대한 정보를 담고 있음
  • DefaultDragVisual : 드래그하는동안 화면에 표시될 비주얼 요소(드래그 되는 아이템 이미지)
  • Pivot : DragVisual의 기준점을 설정. 드래그하는 아이템의 중심을 맞출 수 있음

실제로 Drag를 시작할 때 DragDropOperation을 생성하여 Drag 정보를 초기화 하며, Drag가 종료되면 OnDrop 이벤트가 발생하고, 드롭된 위치에 따라 적절한 처리가 가능합니다.

 

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/creating-drag-and-drop-ui-in-unreal-engine?application_version=5.4

 

실제 클래스를 작성해주도록 합니다.

 

DragSlot Class

더보기
UCLASS()
class TIMELESSADVENTURE_API UTA_DragSlot : public UDragDropOperation
{
	GENERATED_BODY()
	
// Drag 정보 저장용 변수
public:
    // 이전 인덱스 저장
    PPROPERTY(VisibleAnywhere)
    int32 PrevSlotIndex;

    // 이전 슬롯 타입 저장
    UPROPERTY(VisibleAnywhere)
    ESlotType SlotType;
};

드래그 & 드롭 기능 구현 - 마우스 입력 처리

위젯에서 마우스의 입력을 처리하고 드래그 & 드롭 기능을 구현하기 위해서는 다음과 같은 3가지 함수를 오버라이드 해야합니다.

 

NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)

  • NativeOnMouseButtonDown 함수는 UI 위젯 클래스에 마우스 클릭 이벤트를 처리할 때 사용할 수 있는 함수입니다.
  • FGeometry : 위젯의 위치, 크기, 트랜스폼 정보를 포함하는 구조체 (마우스가 위젯의 어느 부분을 클릭하는지 등)
  • FPointerEvent : 마우스 이벤트와 관련된 모든 정보를 포함하는 구조체 (좌클릭, 우클릭 등)

반환값은 FReply로, 마우스 이벤트 처리에 대한 결과를 반환하게 됩니다.

더보기
FReply UTA_Slot::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
    FEventReply Reply;
    Reply.NativeReply = Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);

    // 우클릭 입력이 들어온 경우
    if (InMouseEvent.IsMouseButtonDown(EKeys::RightMouseButton))
    {
    
    }
    // 좌클릭 입력이 들어온 경우
    else if (InMouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton))
    {
        // 정보 체크용 변수
        bool Success = false;

        // 해당 슬롯에 아이템이 존재하는지 체크합니다.
        IInventoryInterface* InvInterface = Cast<IInventoryInterface>(OwnerActor);
        if (InvInterface)
        {
            switch (SlotType)
            {
            case ESlotType::ST_Inventory_C:
                if (IsValid(InvInterface->GetInventory()) && !InvInterface->GetInventory()->GetCInventory()[SlotNum].bIsEmpty)
                {
                    Success = true;
                }
                break;
            case ESlotType::ST_Inventory_M:
                if (IsValid(InvInterface->GetInventory()) && !InvInterface->GetInventory()->GetMInventory()[SlotNum].bIsEmpty)
                {
                    Success = true;
                }
                break;
            case ESlotType::ST_QuickSlot:
                break;
            default:
                break;
            }
        }

        // 유효한 아이템이 존재하는 경우
        if (Success)
        {
            // 드래그 이벤트를 감지하도록 UWidgetBlueprintLibrary::DetectDragIfPressed 함수를 호출합니다.
            Reply = UWidgetBlueprintLibrary::DetectDragIfPressed(InMouseEvent, this, EKeys::LeftMouseButton);
        }
    }

    return Reply.NativeReply;
}

즉 ,좌클릭 시 선택된 슬롯의 아이템이 유효한 경우 DetectDragIfPressed() 함수를 호출하게 되며 드래그가 감지되었을 때 NativeOnDragDetected() 함수가 자동으로 호출됩니다.

 

NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation)

  • NativeOnDragDetected 함수는 드래그&드롭 동작이 감지되었을 대 호출되는 함수입니다.
  • FGeometry : 위젯의 위치, 크기, 트랜스폼 정보를 포함하는 구조체 (마우스가 위젯의 어느 부분을 클릭하는지 등)
  • FPointerEvent : 마우스 이벤트와 관련된 모든 정보를 포함하는 구조체 (좌클릭, 우클릭 등)
  • UDragDropOperation : 드래그&드롭 작업을 관리하는 DragDropOperation 객체 (위에서 생성했던 클래스)
더보기
void UTA_Slot::NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation)
{
    // 드래그가 시작될 때 호출되는 함수
    Super::NativeOnDragDetected(InGeometry, InMouseEvent, OutOperation);

    // 드래그 오퍼가 비어있는 경우
    if (OutOperation == nullptr)
    {
        // 드래그 슬롯을 생성합니다.
        UTA_DragSlot* Operation = NewObject<UTA_DragSlot>();
        OutOperation = Operation;

        // 슬롯과 슬롯 타입을 지정합니다.
        Operation->PrevSlotIndex = SlotNum;
        Operation->SlotType = SlotType;

        // 드래그 시 출력될 위젯을 스폰합니다. (단지 출력 용도)
        if (DragSlotClass)
        {
            UTA_Slot* DragSlot = CreateWidget<UTA_Slot>(GetWorld(), DragSlotClass);
            if (DragSlot)
            {
                // 초기화
                DragSlot->SetOwnerPlayer(OwnerActor);
                DragSlot->SetNum(SlotNum);
                DragSlot->Init(SlotType);
                DragSlot->UpdateSlot();

                // 드래그 슬롯의 드래그 위젯으로 설정합니다.
                Operation->DefaultDragVisual = DragSlot;
            }
        }
    }
}

즉, 기존에 만들었던 DragSlotClass를 생성하여 현재 슬롯 아이템 정보로 초기화하고, DefaultDragVisual로 설정하여 아이템의 아이콘이 마우스 커서를 따라오도록 설정합니다.

 

NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation)

  • NativeOnDrop 함수는 드래그&드롭 작업이 완료되는 경우 호출되는 함수입니다.
  • FGeometry : 위젯의 위치, 크기, 트랜스폼 정보를 포함하는 구조체 (마우스가 위젯의 어느 부분을 클릭하는지 등)
  • FDragDropEvent : 드래그 앤 드롭과 관련된 마우스 이벤트 정보가 담긴 구조체
  • UDragDropOperation : 드래그&드롭 작업을 관리하는 DragDropOperation 객체 (위에서 생성했던 클래스)
더보기
bool UTA_Slot::NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation)
{
    // 드래그가 종료될 때 호출되는 함수
    Super::NativeOnDrop(InGeometry, InDragDropEvent, InOperation);

    // 전달받은 InOperation(UTA_DragSlot)에 저장된 값을 활용해 현재 슬롯과 비교합니다.
    UTA_DragSlot* DragSlot = Cast<UTA_DragSlot>(InOperation);
    if (DragSlot)
    {
        // 슬롯의 타입이 같은 경우
        if (DragSlot->SlotType == SlotType)
        {
            // 인벤토리 내부 위치를 교체합니다.
            IInventoryInterface* InvInterface = Cast<IInventoryInterface>(OwnerActor);
            if (InvInterface)
            {
                InvInterface->GetInventory()->SwapItem(DragSlot->SlotType, DragSlot->PrevSlotIndex, SlotType, SlotNum);
            }
        }
        // 이전 슬롯이 소비 슬롯이고, 현재 슬롯이 퀵슬롯인 경우
        else if (DragSlot->SlotType == ESlotType::ST_Inventory_C && SlotType == ESlotType::ST_QuickSlot)
        {
            // 아이템 등록
            IInventoryInterface* InvInterface = Cast<IInventoryInterface>(OwnerActor);
            if (InvInterface)
            {
                InvInterface->GetInventory()->AddQuickSlot(DragSlot->SlotType, DragSlot->PrevSlotIndex, SlotNum);
            }
        }
    }

    return false;
}

저의 경우 DragSlot에 저장된 정보(슬롯의 타입)와 Drop된 위치의 정보(슬롯의 타입)을 비교하여 개별적으로 처리해주도록 구현하였습니다. 


Slot - 초기화 / 업데이트

각각의 Slot Widget은 초기화 시 타입이 결정되고, 인벤토리 내부 정보가 업데이트 되는 순간 이미지, 수량 등이 업데이트 되어야 합니다.

 

슬롯의 타입에 따라 실제 아이템 데이터에 접근해서 정보를 업데이트 해주도록 합니다.

더보기
void UTA_Slot::Init(ESlotType Type)
{
    SlotType = Type;

    UpdateSlot();
}

void UTA_Slot::UpdateSlot()
{
    if (!OwnerActor) return;
    IInventoryInterface* InvInterface = Cast<IInventoryInterface>(OwnerActor);
    if (InvInterface)
    {
        switch (SlotType)
        {
        case ESlotType::ST_Inventory_C:
            // 해당 슬롯의 정보가 유효한 경우
            if (InvInterface->GetInventory()->GetCInventory().IsValidIndex(SlotNum) && !InvInterface->GetInventory()->GetCInventory()[SlotNum].bIsEmpty)
            {
                // 해당 텍스처 설정
                IMG_ItemIcon->SetBrushFromTexture(InvInterface->GetInventory()->GetCInventory()[SlotNum].Data.ItemThumbnail);
                // 수량 설정
                TXT_Quantity->SetText(FText::FromString(FString::FromInt(InvInterface->GetInventory()->GetCInventory()[SlotNum].Quantity)));
            }
            else
            {
                // 빈 텍스처 설정
                IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
                // 수량 설정
                TXT_Quantity->SetText(FText::FromString(TEXT("")));
            }
            break;
        case ESlotType::ST_Inventory_M:
            // 해당 슬롯의 정보가 유효한 경우
            if (InvInterface->GetInventory()->GetMInventory().IsValidIndex(SlotNum) && !InvInterface->GetInventory()->GetMInventory()[SlotNum].bIsEmpty)
            {
                // 해당 텍스처 설정
                IMG_ItemIcon->SetBrushFromTexture(InvInterface->GetInventory()->GetMInventory()[SlotNum].Data.ItemThumbnail);
                // 수량 설정
                TXT_Quantity->SetText(FText::FromString(FString::FromInt(InvInterface->GetInventory()->GetMInventory()[SlotNum].Quantity)));
            }
            else
            {
                // 빈 텍스처 설정
                IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
                // 수량 설정
                TXT_Quantity->SetText(FText::FromString(TEXT("")));
            }
            break;
        case ESlotType::ST_QuickSlot:
            // 해당 슬롯의 인덱스가 유효한 경우
            if (InvInterface->GetInventory()->GetQuickSlot().IsValidIndex(SlotNum) && !(InvInterface->GetInventory()->GetQuickSlot()[SlotNum] == -1))
            {
                int32 Index = InvInterface->GetInventory()->GetQuickSlot()[SlotNum];

                // 해당 슬롯의 정보가 유효한 경우
                if (InvInterface->GetInventory()->GetCInventory().IsValidIndex(SlotNum) && !InvInterface->GetInventory()->GetCInventory()[Index].bIsEmpty)
                {
                    // 해당 텍스처 설정
                    IMG_ItemIcon->SetBrushFromTexture(InvInterface->GetInventory()->GetCInventory()[Index].Data.ItemThumbnail);
                    // 수량 설정
                    TXT_Quantity->SetText(FText::FromString(FString::FromInt(InvInterface->GetInventory()->GetCInventory()[Index].Quantity)));
                }
                else
                {
                    // 빈 텍스처 설정
                    IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
                    // 수량 설정
                    TXT_Quantity->SetText(FText::FromString(TEXT("")));
                }
            }
            else
            {
                // 빈 텍스처 설정
                IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
                // 수량 설정
                TXT_Quantity->SetText(FText::FromString(TEXT("")));
            }
            break;
        default:
            break;
        }
    }
    else
    {
        if (SlotType == ESlotType::ST_Shop)
        {
            if (ATA_Stone* Stone = Cast<ATA_Stone>(OwnerActor))
            {
                if (Stone->GetShopItemData().IsValidIndex(SlotNum))
                {
                    // 텍스처 설정
                    IMG_ItemIcon->SetBrushFromTexture(Stone->GetShopItemData()[SlotNum].ItemThumbnail);
                }
                else
                {
                    IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
                }
            }
        }
    }
    
}

Slot Class 전체 코드

Slot.h

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

#pragma once

#include "CoreMinimal.h"
#include "UI/TA_CustomWidget.h"
#include "Data/TA_SlotType.h"
#include "TA_Slot.generated.h"

/**
 * 
 */
UCLASS()
class TIMELESSADVENTURE_API UTA_Slot : public UTA_CustomWidget
{
	GENERATED_BODY()
	
protected:
	virtual void NativeConstruct() override;

	virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
	virtual void NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation) override;
	bool NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override;

public:
	FORCEINLINE void SetNum(int32 Num) { SlotNum = Num; }
	void Init(ESlotType Type);
	void UpdateSlot();


private:
	// 아이템 아이콘
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UImage> IMG_ItemIcon;

	// 아이템 수량
	UPROPERTY(meta = (BindWidget))
	TObjectPtr<class UTextBlock> TXT_Quantity;
    
	// 슬롯의 타입
	ESlotType SlotType;

    // 슬롯의 인덱스
	UPROPERTY(EditAnywhere, Category = "Slot", meta = (AllowPrivateAccess = "true"))
	int32 SlotNum;

    // 빈 아이템 아이콘
	UPROPERTY(EditAnywhere, Category = "Slot", meta = (AllowPrivateAccess = "true"))
	TObjectPtr<class UTexture2D> NoneTexture;

    // 드래그에 사용될 Slot Class
	UPROPERTY(EditAnywhere, Category = "Slot")
	TSubclassOf<UTA_Slot> DragSlotClass;
};

Slot.cpp

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


#include "UI/TA_Slot.h"
#include "Interface/InventoryInterface.h"
#include "Component/TA_InventoryComponent.h"
#include "UI/TA_DragSlot.h"
#include "Gimmick/TA_Stone.h"

#include "Components/Image.h"
#include "Components/TextBlock.h"
#include "Blueprint/WidgetBlueprintLibrary.h"

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

FReply UTA_Slot::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
	FEventReply Reply;
	Reply.NativeReply = Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);

	// 우클릭 입력이 들어온 경우
	if (InMouseEvent.IsMouseButtonDown(EKeys::RightMouseButton))
	{
	}
	// 좌클릭 입력이 들어온 경우
	else if (InMouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton))
	{
		// 정보 체크용 변수
		bool Success = false;

		// 해당 슬롯에 아이템이 존재하는지 체크합니다.
		IInventoryInterface* InvInterface = Cast<IInventoryInterface>(OwnerActor);
		if (InvInterface)
		{
			switch (SlotType)
			{
			case ESlotType::ST_Inventory_C:
				if (IsValid(InvInterface->GetInventory()) && !InvInterface->GetInventory()->GetCInventory()[SlotNum].bIsEmpty)
				{
					Success = true;
				}
				break;
			case ESlotType::ST_Inventory_M:
				if (IsValid(InvInterface->GetInventory()) && !InvInterface->GetInventory()->GetMInventory()[SlotNum].bIsEmpty)
				{
					Success = true;
				}
				break;
			case ESlotType::ST_QuickSlot:
				break;
			default:
				break;
			}
		}

		// 유효한 아이템이 존재하는 경우
		if (Success)
		{
			Reply = UWidgetBlueprintLibrary::DetectDragIfPressed(InMouseEvent, this, EKeys::LeftMouseButton);
		}
	}

	return Reply.NativeReply;
}

void UTA_Slot::NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation)
{
	// 드래그가 시작될 때 호출되는 함수
	Super::NativeOnDragDetected(InGeometry, InMouseEvent, OutOperation);

	// 드래그 오퍼가 비어있는 경우
	if (OutOperation == nullptr)
	{
		// 드래그 슬롯을 생성합니다.
		UTA_DragSlot* Operation = NewObject<UTA_DragSlot>();
		OutOperation = Operation;

		// 슬롯과 슬롯 타입을 지정합니다.
		Operation->PrevSlotIndex = SlotNum;
		Operation->SlotType = SlotType;

		// 드래그 시 출력될 위젯을 스폰합니다. (단지 출력 용도)
		if (DragSlotClass)
		{
			UTA_Slot* DragSlot = CreateWidget<UTA_Slot>(GetWorld(), DragSlotClass);
			if (DragSlot)
			{
				// 초기화
				DragSlot->SetOwnerPlayer(OwnerActor);
				DragSlot->SetNum(SlotNum);
				DragSlot->Init(SlotType);
				DragSlot->UpdateSlot();

				// 드래그 슬롯의 드래그 위젯으로 설정합니다.
				Operation->DefaultDragVisual = DragSlot;
			}
		}
	}
}

bool UTA_Slot::NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation)
{
	// 드래그가 종료될 때 호출되는 함수
	Super::NativeOnDrop(InGeometry, InDragDropEvent, InOperation);

	// 전달받은 InOperation(UTA_DragSlot)에 저장된 값을 활용해 현재 슬롯과 비교합니다.
	UTA_DragSlot* DragSlot = Cast<UTA_DragSlot>(InOperation);
	if (DragSlot)
	{
		// 슬롯의 타입이 같은 경우
		if (DragSlot->SlotType == SlotType)
		{
			// 인벤토리 내부 위치를 교체합니다.
			IInventoryInterface* InvInterface = Cast<IInventoryInterface>(OwnerActor);
			if (InvInterface)
			{
				InvInterface->GetInventory()->SwapItem(DragSlot->SlotType, DragSlot->PrevSlotIndex, SlotType, SlotNum);
			}
		}
		// 이전 슬롯이 소비 슬롯이고, 현재 슬롯이 퀵슬롯인 경우
		else if (DragSlot->SlotType == ESlotType::ST_Inventory_C && SlotType == ESlotType::ST_QuickSlot)
		{
			// 아이템 등록
			IInventoryInterface* InvInterface = Cast<IInventoryInterface>(OwnerActor);
			if (InvInterface)
			{
				InvInterface->GetInventory()->AddQuickSlot(DragSlot->SlotType, DragSlot->PrevSlotIndex, SlotNum);
			}
		}
	}

	return false;
}

void UTA_Slot::Init(ESlotType Type)
{
	SlotType = Type;

	UpdateSlot();
}

void UTA_Slot::UpdateSlot()
{
	if (!OwnerActor) return;
	IInventoryInterface* InvInterface = Cast<IInventoryInterface>(OwnerActor);
	if (InvInterface)
	{
		switch (SlotType)
		{
		case ESlotType::ST_Inventory_C:
			// 해당 슬롯의 정보가 유효한 경우
			if (InvInterface->GetInventory()->GetCInventory().IsValidIndex(SlotNum) && !InvInterface->GetInventory()->GetCInventory()[SlotNum].bIsEmpty)
			{
				// 해당 텍스처 설정
				IMG_ItemIcon->SetBrushFromTexture(InvInterface->GetInventory()->GetCInventory()[SlotNum].Data.ItemThumbnail);
				// 수량 설정
				TXT_Quantity->SetText(FText::FromString(FString::FromInt(InvInterface->GetInventory()->GetCInventory()[SlotNum].Quantity)));
			}
			else
			{
				// 빈 텍스처 설정
				IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
				// 수량 설정
				TXT_Quantity->SetText(FText::FromString(TEXT("")));
			}
			break;
		case ESlotType::ST_Inventory_M:
			// 해당 슬롯의 정보가 유효한 경우
			if (InvInterface->GetInventory()->GetMInventory().IsValidIndex(SlotNum) && !InvInterface->GetInventory()->GetMInventory()[SlotNum].bIsEmpty)
			{
				// 해당 텍스처 설정
				IMG_ItemIcon->SetBrushFromTexture(InvInterface->GetInventory()->GetMInventory()[SlotNum].Data.ItemThumbnail);
				// 수량 설정
				TXT_Quantity->SetText(FText::FromString(FString::FromInt(InvInterface->GetInventory()->GetMInventory()[SlotNum].Quantity)));
			}
			else
			{
				// 빈 텍스처 설정
				IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
				// 수량 설정
				TXT_Quantity->SetText(FText::FromString(TEXT("")));
			}
			break;
		case ESlotType::ST_QuickSlot:
			// 해당 슬롯의 인덱스가 유효한 경우
			if (InvInterface->GetInventory()->GetQuickSlot().IsValidIndex(SlotNum) && !(InvInterface->GetInventory()->GetQuickSlot()[SlotNum] == -1))
			{
				int32 Index = InvInterface->GetInventory()->GetQuickSlot()[SlotNum];

				// 해당 슬롯의 정보가 유효한 경우
				if (InvInterface->GetInventory()->GetCInventory().IsValidIndex(SlotNum) && !InvInterface->GetInventory()->GetCInventory()[Index].bIsEmpty)
				{
					// 해당 텍스처 설정
					IMG_ItemIcon->SetBrushFromTexture(InvInterface->GetInventory()->GetCInventory()[Index].Data.ItemThumbnail);
					// 수량 설정
					TXT_Quantity->SetText(FText::FromString(FString::FromInt(InvInterface->GetInventory()->GetCInventory()[Index].Quantity)));
				}
				else
				{
					// 빈 텍스처 설정
					IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
					// 수량 설정
					TXT_Quantity->SetText(FText::FromString(TEXT("")));
				}
			}
			else
			{
				// 빈 텍스처 설정
				IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
				// 수량 설정
				TXT_Quantity->SetText(FText::FromString(TEXT("")));
			}
			break;
		default:
			break;
		}
	}
	else
	{
		if (SlotType == ESlotType::ST_Shop)
		{
			if (ATA_Stone* Stone = Cast<ATA_Stone>(OwnerActor))
			{
				if (Stone->GetShopItemData().IsValidIndex(SlotNum))
				{
					// 텍스처 설정
					IMG_ItemIcon->SetBrushFromTexture(Stone->GetShopItemData()[SlotNum].ItemThumbnail);
				}
				else
				{
					IMG_ItemIcon->SetBrushFromTexture(NoneTexture);
				}
			}
		}
	}
	
}
728x90
반응형