0. 개요

MVVM 모델에서 뷰와 뷰 모델은 일대일 대응 관계를 가진다.

로드 메뉴에서 세 개의 슬롯은 각각의 뷰 모델을 가지게 될 것이다.

 

 

1. 뷰 모델

위젯 스위쳐 내의 세 하위 위젯도 상위 위젯의 로드 슬롯 뷰 모델을 가지게 된다

 

(1) 각 슬롯에 할당할 MVVM_LoadSlot 뷰 모델 C++ 클래스 생성

MVVM View Model Base를 상속받는 C++ 클래스를 생성한다.

 

(2) UMVVM_LoadScreen에서 각 슬롯의 뷰 모델을 멤버 변수로 저장

#include "CoreMinimal.h"
#include "MVVMViewModelBase.h"
#include "MVVM_LoadScreen.generated.h"

class UMVVM_LoadSlot;

UCLASS()
class AURA_API UMVVM_LoadScreen : public UMVVMViewModelBase
{
	GENERATED_BODY()

public:
	void InitializeLoadSlots();

public:
	UPROPERTY(EditDefaultsOnly)
	TSubclassOf<UMVVM_LoadSlot> LoadSlotViewModelClass;

private:
	UPROPERTY()
	TMap<int32, UMVVM_LoadSlot*> LoadSlots;

	UPROPERTY()
	TObjectPtr<UMVVM_LoadSlot> LoadSlot_0;

	UPROPERTY()
	TObjectPtr<UMVVM_LoadSlot> LoadSlot_1;

	UPROPERTY()
	TObjectPtr<UMVVM_LoadSlot> LoadSlot_2;
};
#include "UI/ViewModel/MVVM_LoadScreen.h"
#include "UI/ViewModel/MVVM_LoadSlot.h"

void UMVVM_LoadScreen::InitializeLoadSlots()
{
	LoadSlot_0 = NewObject<UMVVM_LoadSlot>(this, LoadSlotViewModelClass);
	LoadSlot_1 = NewObject<UMVVM_LoadSlot>(this, LoadSlotViewModelClass);
	LoadSlot_2 = NewObject<UMVVM_LoadSlot>(this, LoadSlotViewModelClass);

	LoadSlots.Add(0, LoadSlot_0);
	LoadSlots.Add(1, LoadSlot_1);
	LoadSlots.Add(2, LoadSlot_2);
}

MVVM_LoadScreen은 로드 메뉴의 뷰 모델들을 관리하는 뷰 모델이다.

- 각 슬롯(총 3개 슬롯)마다 뷰 모델이 하나씩 있음

- 세 개의 뷰 모델을 TMap으로 관리

 


로드 메뉴의 MVVM 구성은 아래와 같다.

- 뷰 : LoadScreenHUD

- 모델 : 인 게임 데이터(이름, 레벨, 맵 이름, 세이브 데이터 등등)

- 뷰 모델 : MVVM_LoadScreen

 

로드 슬롯의 MVVM 구성은 아래와 같다.

- 뷰 : WBP_LoadSlot_WidgetChanger

- 모델 : 인 게임 데이터(이름, 레벨, 맵 이름, 세이브 데이터 등등)

- 뷰 모델 : MVVM_LoadSlot

 

한편, 로드 슬롯의 뷰 모델 3개는 MVVM_LoadScreen에서 관리한다.


 

(3) LoadScreenHUD에서 로드 슬롯 초기화 함수 호출

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

	// 로드 메뉴의 뷰 모델 생성
	LoadScreenViewModel = NewObject<UMVVM_LoadScreen>(this, LoadScreenViewModelClass);

	// 뷰 모델 초기화
	LoadScreenViewModel->InitializeLoadSlots();

	// 뷰 생성
	LoadScreenWidget = CreateWidget<ULoadScreenWidget>(GetWorld(), LoadScreenWidgetClass);
	LoadScreenWidget->AddToViewport();
}

 

 

(4) MVVM_LoadSlot(C++ 클래스)를 기반으로 하는 BP_LoadSlotViewModel 블루프린트 클래스 생성

(4-1) BP_LoadScreenViewModel에서 로드 슬롯 뷰 모델 클래스 지정

 

 

(5) HUD에서 로드 메뉴의 뷰 모델에서 로드 슬롯의 뷰 모델에 접근하기

MVVM_LoadScreen에서 로드 슬롯의 뷰 모델을 가지고 있다.

로드 슬롯의 뷰 모델을 가져오는 Getter를 만든다.

	UFUNCTION(BlueprintPure)
	UMVVM_LoadSlot* GetLoadSlotViewModelByIndex(int32 Index);
UMVVM_LoadSlot* UMVVM_LoadScreen::GetLoadSlotViewModelByIndex(int32 Index)
{
	return LoadSlots.FindChecked(Index);
}

 

 

(6) 각 로드 슬롯을 초기화 시키기

각 로드 슬롯의 뷰가 블루프린트에서 초기화 되도록 설정한다.

로드 슬롯의 뷰 클래스인 LoadScreenWidget에 블루프린트 이벤트 타입의 초기화 함수를 만든다.

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "LoadScreenWidget.generated.h"

UCLASS()
class AURA_API ULoadScreenWidget : public UUserWidget
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintImplementableEvent, BlueprintCallable)
	void BlueprintInitializeWidget();
};

그리고 HUD에서 블루프린트 이벤트 함수를 호출한다.

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

	// 로드 메뉴의 뷰 모델 생성
	LoadScreenViewModel = NewObject<UMVVM_LoadScreen>(this, LoadScreenViewModelClass);

	// 뷰 모델 초기화 - 로드 슬롯의 뷰 모델 생성
	LoadScreenViewModel->InitializeLoadSlots();

	// 로드 메뉴의 뷰 생성
	LoadScreenWidget = CreateWidget<ULoadScreenWidget>(GetWorld(), LoadScreenWidgetClass);
	LoadScreenWidget->AddToViewport();

	// 로드 메뉴의 뷰를 블루프린트에서 초기화 시킴
	LoadScreenWidget->BlueprintInitializeWidget();
}

 

 

(7) WBP_LoadScreen에서 위젯 스위처들을 변수로 만들기

각 로드 슬롯의 뷰를 변수로 만들고 뷰 모델과 매칭시킬 것이다.

 

 

(7-1) WBP_LoadScreenWidget_Base에서 로드 슬롯의 인덱스를 멤버 변수로 만들기

3개의 로드 슬롯에 0번, 1번, 2번을 할당할 것이다.

멤버 변수를 만들고 눈 아이콘을 눌러 인스턴스 편집 가능으로 만든다.

 

(7-2) WBP_LoadSlot_WidgetSwitcher에서 매개 변수를 SlotIndex의 값으로 지정하는 함수 만들기

 

(7-3) BlueprintInitailizeWidget 함수에서 각 슬롯에 인덱스 부여하기

이 작업을 통해 C++과 블루프린트 모두에서 각 슬롯에 고유 번호가 할당되었다.

 

 

(8) 각 슬롯에 뷰 모델 추가

한 슬롯에 위의 세 유형의 슬롯이 들어가는데, 각각이 다른 상태를 가져야 하기 때문에 이들 슬롯은 각각의 뷰 모델을 가진다.

 

 

2. 뷰에 뷰 모델 할당하기

이제 각 슬롯에 고유 번호가 부여되었으므로, 슬롯 내의 3개 형태의 위젯에도 해당 고유 번호를 부여해야 한다.


ex) 1번 슬롯

- Vacant 타입, Taken 타입, EnterName 타입 모두 1번 인덱스를 가져야 함.


(1) WBP_LoadSlot_WidgetSwitcher에서 뷰(로드 슬롯)에 뷰 모델 할당

(1-1) 슬롯의 세 가지 형태를 멤버 변수로 만듬

 

 

(1-2) InitializeSlot 함수에서 해당 슬롯의 뷰 모델 가져오기

각 슬롯의 고유 번호를 사용하고, TMap에 번호를 대입하여 BP 버전의 로드 슬롯 뷰 모델을 가져온다.

 

 

(1-3) 뷰에 슬롯 인덱스와 뷰 모델 할당하기

이전에 MVC 모델의 하위 위젯에 부모 위젯의 위젯 컨트롤러를 부여하는 것과 동일하다.

이로써 위젯 스위처 내의 세 가지 타입의 위젯이 동일한 슬롯 고유 번호와 뷰 모델을 가지게 되었다.


- 위젯(뷰)와 뷰 모델은 일대일 관계이지만, 하위 위젯(Vacant, Taken, EnterName)은 위젯(뷰)의 뷰 모델 하나만 가지는 다대일 관계이다.