글을 쓰는 목적
Unreal Editor에서 사용자가 만든 변수를 위한 Custom Layout을 디테일 패널에 적용하는 방법을 기록한다. 기존 자료는 많이 있는데 TArray 형태에서 사용할때 깨지는 현상 등 유의해야할 점이 있어서 기록을 남긴다.
작업 환경
UE42.6
사용법
1. 구조체 선언
예를 들어 아래와 같이 사용자가 만든 Struct 구조체가 있다고 하자
//Custom layout을 적용할 구조체
USTRUCT(BlueprintType)
struct FTestValue
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, Category = "Test")
FName TestName;
};
위에서 선언한 구조체에 DetailPanel에 표현되는 기본 레이아웃 말고 자신이 원하는 레이아웃으로 표현해주고 싶다. 예시로 SearchableComoBox 를 적용해서 유저가 ComboBox에서 자신이 원하는 값을 TestName으로 적용하는 레이아웃을 만들어보자.
2. Customized Property Layout을 위한 클래스 만들기
위에서 말한 것 처럼 ComboBox를 눌러서 TestName에 ComboBox 값을 채워줄 것이다. 이를 위해 아래의 FTestValuePropeprtyTypeCustomization Header에 아래와 같은 변수를 선언해 준다.
- TestName의 변수를 변경하기 위 한 TSharedPtr<IPropertyHandle> TestValue 선언
- 콤보 박스를 사용하기 위한 TSharedPtr<SSearchableComboBox> TestSearchableCombox를 Header에 선언
- IPropertyTypeCustomization을 상속 받았기 때문에 기본으로 프로퍼티 해더 부분을 구현하는 CutomizeHeader와 Property 실제 구현 부를 표현하는 CustomizeChildren 을 Override 밑 구현해 준다.
- TestSearchableCombobox를 위한 변수 순언
- 마지막으로 LayoutClass를 Editor에 등록하기 위해 TSharedRef<IPropertyTypeCustomization> MakeInstance를 선언해 준다.
Customized property layout class header
#include <IDetailCustomization.h>
#include <PropertyHandle.h>
#include <IPropertyTypeCustomization.h>
#include <DetailWidgetRow.h>
#include "Editor/EditorWidgets/Public/SSearchableComboBox.h"
#include "IPropertyUtilities.h"
//FTestValue에 적용할 Custom layout 클래스
class FTestValuePropertyTypeCustomization : public IPropertyTypeCustomization
{
//FTestValue의 TestValue의 값을 핸들링할 TestValue
public:
TSharedPtr<IPropertyHandle> TestValue;
//FTestValue의 TestValue의 값을 표현할 Slate 변수
public:
TSharedPtr<SSearchableComboBox> TestSearchableComboBox;
//IPropertyTypeCustomization 상속받을 변수
public:
static TSharedRef<IPropertyTypeCustomization > MakeInstance();
virtual void CustomizeHeader(TSharedRef<IPropertyHandle> inPropertyHandle, FDetailWidgetRow& inHeaderRow, IPropertyTypeCustomizationUtils& inCustomizationUtils) override;
virtual void CustomizeChildren(TSharedRef<IPropertyHandle> inPropertyHandle, IDetailChildrenBuilder& inChildBuilder, IPropertyTypeCustomizationUtils& inCustomizationUtils) override;
public:
TSharedRef<SWidget> OnSearchableComboboxGenerateWidget(TSharedPtr<FString> inItem);
void OnSearchableComboboxSelectChanged(TSharedPtr<FString> inNewSelection, ESelectInfo::Type inSelectInfo);
bool IsSearchableComboboxEnabled() const;
FText GetSearchableComboboxContent() const;
FText GetSearchableComboboxToolTip() const;
}
Customized property layout class cpp
//Editor에 등록할 때 사용할 인스턴스
TSharedRef<IPropertyTypeCustomization > FTestPropertyTypeCustomization::MakeInstance()
{
return MakeShareable(new FTestPropertyTypeCustomization);
}
//커스터 마이징 Header 부분
void FTestPropertyTypeCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> inPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& inCustomizationUtils)
{
HeaderRow.NameContent()
[
inPropertyHandle->CreatePropertyNameWidget(FText::GetEmpty(), FText::GetEmpty(), false)
];
TestValueHandler = inPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FTestValue, TestValue));
}
//Slate 커스터 마아징 부분
void FTestPropertyTypeCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> inPropertyHandle, IDetailChildrenBuilder& inChildBuilder, IPropertyTypeCustomizationUtils& inCustomizationUtils)
{
//구현부
PropertyUtilities = inCustomizationUtils.GetPropertyUtilities();
inPropertyHandle.AddCustomRow(LOCTEXT("TestValue", "TableValue"))
.NameContents()
[
SNew(STextBlock).Text(LOCTEXT("TestValue", "Table TestValue"))
]
.SNew(SHorizontalBox)
.AutoWidth()
.VAlign(VAlign_Center)
.Padding(3.0, 0.0, 3.0, 0.0)
[
SAssignNew(TestSearchableComboBox, SSearchableComboBox)
.OptionsSource(&TableNameList)
.OnGenerateWidget(this, &FTestPropertyTypeCustomization::OnSearchableComboboxGenerateWidget)
.OnSelectionChanged(this, &FTestPropertyTypeCustomization::OnSearchableComboboxSelectChanged)
.IsEnabled(this, &FTestPropertyTypeCustomization::IsSearchableComboboxEnabled)
.ContentPadding(2)
.Content()
[
SNew(STextBlock)
.Text(this, &FTestPropertyTypeCustomization::GetSearchableComboboxContent)
.ToolTipText(this, &FTestPropertyTypeCustomization::GetSearchableComboboxToolTip)
]
]
}
TSharedRef<SWidget> FTestPropertyTypeCustomization::OnSearchableComboboxGenerateWidget(TSharedPtr<FString> inItem)
{
return TSharedRef<SWidget>();
}
void FTestPropertyTypeCustomization::OnSearchableComboboxSelectChanged(TSharedPtr<FString> inNewSelection, ESelectInfo::Type inSelectInfo)
{
//bla bla
}
bool FTestPropertyTypeCustomization::IsSearchableComboboxEnabled()
{
return true;
}
FText FTestPropertyTypeCustomization::GetSearchableComboboxContent() const
{
return FText();
}
FText FTestPropertyTypeCustomization::GetSearchableComboboxToolTip() const
{
return FText();
}
3. Layout 등록
위에 있는 FTestValue와 IPropertyTypeCustomization 을 상속한 FTestValuePropertyTypeCustomization를 커스텀 에디터 에디터 모듈에 등록해준다. 구조체 같은 경우 FTestValue라고 구조체 이름이 이렇게 정의되어 있다면 TestValue로 이름을 넣으셔서 등록한다.
void FTestEditorModule::RegisterCustomPropertyTypeLayouts()
{
auto& propertyModule = FModuleManager::LoadModuleChecked< FPropertyEditorModule >("PropertyEditor");
propertyModule.RegisterCustomPropertyTypeLayout("TestValue", FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FTestValuePropertyTypeCustomization::MakeInstance));
propertyModule.NotifyCustomizationModuleChanged();
}
void FTestEditorModule::UnregisterCustomPropertyTypeLayouts()
{
if (FModuleManager::Get().IsModuleLoaded("PropertyEditor"))
{
auto & propertyModule = FModuleManager::LoadModuleChecked <FPropertyEditorModule>("PropertyEditor");
propertyModule.UnregisterCustomPropertyTypeLayout("TestValue");
}
}
주의 사항
배열에서 Customized property가 이상하게 나올 때
참고 자료에 자세히 나와 있어 따라하는데 크게 어렵지 않았는데 배열 구조체에 적용하려고 하니 프로퍼티 헤더가 안나오는 현상이 있었다. 프로퍼티 헤더를 오타로 인해 제대로 구현안해서 발생한 문제였는데 프로퍼티 헤더 선언이 이상해도 일단 출력은 되는 것 같다. 선언과 구현을 정상적으로 하면 배열에서도 이상 없이 사용할 수 있었다.
참고
https://forums.unrealengine.com/t/help-with-details-panel-customization/76425
'UE4' 카테고리의 다른 글
UE4 UMG에서 BindWidget 된 상태에서 SetVisiblity를 통해 보이게 했지만 작동하지 않는 경우 (0) | 2021.07.15 |
---|---|
UE4 UMG에서 RenderTarget 사용 방법 (0) | 2021.07.15 |
[UE4][Firebase] EasyFirebase Upload symbol (0) | 2021.06.04 |
UE4.26 IOS remote build (0) | 2021.05.12 |
UE4.26 Android Build (2) | 2021.05.11 |