UE4_C++_自定義細節面板_Customizing detail panels

UE4_C++_自定義細節面板_Customizing detail panels

概述

本文主要討論自定義細節面板的製作,包含顯示分類及屬性信息。
版本:420
模塊:PropertyEditor

定製類型

  • 默認佈局
    在C++中,只要你的屬性以 UPROPERTY宏修飾且爲常用類型,Editor系統將會爲此屬性創建一個默認佈局。

  • 自定義屬性
    當你創建一個自定義結構時,若想編輯器爲其創建佈局,必須以UStruct修飾;但若是你想爲細節面板添加按鈕,或其他定製化控件,以實現某些功能時,本文可以爲你提供一個參考。
    在IPropertyTypeCustomization的實現中,接口CustomizeHeader和CustomizeChildren提供了屬性的擴展功能。我們需要創建IPropertyTypeCustomization的子類,如下:

//MyStructCustomization.h

#include "Editor/DetailCustomizations/Private/DetailCustomizationsPrivatePCH.h"

#pragma once

class FMyStructCustomization : public IPropertyTypeCustomization
{
public:
	static TSharedRef<IPropertyTypeCustomization> MakeInstance();

	/** IPropertyTypeCustomization interface */
	virtual void CustomizeHeader(TSharedRef<class IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;
	virtual void CustomizeChildren(TSharedRef<class IPropertyHandle> StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override;

private:
	TSharedPtr<IPropertyHandle> SomeUPropertyHandle;
};
////MyStructCustomization.cpp

#include "DetailCustomizations/MyStructCustomization.h"

#define LOCTEXT_NAMESPACE "MyStructCustomization"

TSharedRef<IPropertyTypeCustomization> FMyStructCustomization::MakeInstance()
{
	return MakeShareable(new FMyStructCustomization());
}

void FMyStructCustomization::CustomizeHeader(TSharedRef<class IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
	uint32 NumChildren;
	StructPropertyHandle->GetNumChildren(NumChildren);

	for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex)
	{
		const TSharedRef< IPropertyHandle > ChildHandle = StructPropertyHandle->GetChildHandle(ChildIndex).ToSharedRef();

		if (ChildHandle->GetProperty()->GetName() == TEXT("SomeUProperty"))
		{
			SomeUPropertyHandle = ChildHandle;
		}
	}

	check(SomeUPropertyHandle.IsValid());


	HeaderRow.NameContent()
		[
			StructPropertyHandle->CreatePropertyNameWidget(TEXT("New property header name"), false)
		]
	.ValueContent()
		.MinDesiredWidth(500)
		[
			SNew(STextBlock)
			.Text(LOCTEXT("Extra info", "Some new representation"))
			.Font(IDetailLayoutBuilder::GetDetailFont())
		];
}

void FMyStructCustomization::CustomizeChildren(TSharedRef<class IPropertyHandle> StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
    //Create further customization here
}

#undef LOCTEXT_NAMESPACE

其中,CustomizeHeader 從自定義結構體MyStruct 中提取SomeUProperty屬性初始化屬性SomeUPropertyHandle,然偶以Slate代碼覆寫細節面板。(關於Slate的學習可查閱官方文檔)

  • 自定義Object(細節面板)
    如果你想自定義結構展示,也想控制整個detail面板的渲染,如自定義分類和其具體細節等等,實現IDetailCustomization接口即可;如下:
//MyClassDetails.h

#include "Editor/DetailCustomizations/Private/DetailCustomizationsPrivatePCH.h"

#pragma once

class FMyClassDetails : public IDetailCustomization
{
public:
	/** Makes a new instance of this detail layout class for a specific detail view requesting it */
	static TSharedRef<IDetailCustomization> MakeInstance();

	/** IDetailCustomization interface */
	virtual void CustomizeDetails( IDetailLayoutBuilder& DetailBuilder ) override;
};
////MyClassDetails.cpp

#include "MyProjectPCH.h"

#include "DetailCustomizations/MyClassDetails.h"

#define LOCTEXT_NAMESPACE "MyClassDetails"

TSharedRef<IDetailCustomization> FMyClassDetails::MakeInstance()
{
	return MakeShareable(new FMyClassDetails);
}

void FMyClassDetails::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
	// Create a category so this is displayed early in the properties
	IDetailCategoryBuilder& MyCategory = DetailBuilder.EditCategory("CategoryName", TEXT("Extra info"), ECategoryPriority::Important);

        //You can get properties using the detailbuilder
	//MyProperty= DetailBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(MyClass, MyClassPropertyName));

	MyCategory.AddCustomRow(LOCTEXT("Extra info", "Row header name").ToString())
		.NameContent()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("Extra info", "Custom row header name"))
			.Font(IDetailLayoutBuilder::GetDetailFont())
		]
		.ValueContent().MinDesiredWidth(500)
		[
			SNew(STextBlock)
			.Text(LOCTEXT("Extra info", "Custom row content"))
			.Font(IDetailLayoutBuilder::GetDetailFont())
		];
}

#undef LOCTEXT_NAMESPACE
其中CustomizeDetails 函數創建了分類"CategoryName",然後在分類"CategoryName"下新建名稱爲"Custom row header name",內容爲"Custom row content"的屬性。

面板註冊

以上已經成功創建出了我們所需的細節面板,但爲了讓UE4編輯器知道該定製的存在,還需要註冊正確的模板。本步驟可在解決方案的任何位置進行,但爲了避免不可預期的錯誤,推薦僅在一些代碼僅運行一次的地方進行。如:主遊戲模塊或者game mode中。
在build.cs中包含PropertyEditor,如下:
 PrivateDependencyModuleNames.AddRange(
                new string[] {
                    "Core",
                    "CoreUObject",
                    "Engine",
                    "UnrealEd",
                    "AssetTools",
                    "Projects",
                    "Slate",
                    "EditorStyle",
                    "SlateCore",
                    "PropertyEditor"
                }

在合適的位置進行註冊,自定義屬性使用RegisterCustomPropertyTypeLayout,如下:

FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");

	//Custom properties
	PropertyModule.RegisterCustomPropertyTypeLayout("MyStruct", FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FMyStructCustomization::MakeInstance));

自定義object使用RegisterCustomClassLayout,如下:

FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");

	//Custom detail views
	PropertyModule.RegisterCustomClassLayout("MyClass", FOnGetDetailCustomizationInstance::CreateStatic(&FMyClassDetails::MakeInstance));

注:輸入的字符串爲自定義類型去除修飾符,如UMyClass,則應輸入MyClass。本例子寫在插件中,因此註冊寫在了插件的StartupModule函數中

官方資源

引擎源碼
Source/Editor/DetailCustomizations/Private/DetailCustomizations.cpp
可供讀者參考

自定義分類的使用可參考:

Source/Editor/DetailCustomizations/Private/StaticMeshComponentDetails.h 
Source/Editor/DetailCustomizations/Private/StaticMeshComponentDetails.cpp

自定義屬性可參考:

Source/Editor/DetailCustomizations/Private/SlateColorCustomization.h 
Source/Editor/DetailCustomizations/Private/SlateColorCustomization.cpp
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章