How to do it...

  1. From the Chapter_10Editor folder, create two new files called MyCustomAssetDetailsCustomization.h and MyCustomAssetDetailsCustomization.cpp.
  2. Return to your project file and update your Visual Studio project. Once finished, open up the project in Visual Studio.
  3. Add the following #pragma and #includes to the header (MyCustomAssetDetailsCustomization.h):
#pragma once

#include "MyCustomAsset.h" #include "DetailLayoutBuilder.h" #include "IDetailCustomization.h" #include "IPropertyTypeCustomization.h"
  1. Define our customization class, as follows:
class FMyCustomAssetDetailsCustomization : public IDetailCustomization
{

public:
virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;

void ColorPicked(FLinearColor SelectedColor);

static TSharedRef<IDetailCustomization> MakeInstance()
{
return MakeShareable(new FMyCustomAssetDetailsCustomization);
}

TWeakObjectPtr<class UMyCustomAsset> MyAsset;
};
  1. Below that, define the following additional class:
class FMyCustomAssetPropertyDetails : public IPropertyTypeCustomization
{
public:
void ColorPicked(FLinearColor SelectedColor);
static TSharedRef<IPropertyTypeCustomization> MakeInstance()
{
return MakeShareable(new FMyCustomAssetPropertyDetails);
}

UMyCustomAsset* MyAsset;
virtual void CustomizeChildren(TSharedRef<IPropertyHandle> PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils) override;

virtual void CustomizeHeader(TSharedRef<IPropertyHandle> PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils) override;

};
  1. In the implementation file, add the following includes at the top of the file:
#include "MyCustomAssetDetailsCustomization.h" 
#include "Chapter_10Editor.h"
#include "IDetailsView.h"
#include "DetailLayoutBuilder.h"
#include "DetailCategoryBuilder.h"
#include "SColorPicker.h"
#include "SBoxPanel.h"
#include "DetailWidgetRow.h"
  1. Afterwards, create an implementation for CustomizeDetails:
void FMyCustomAssetDetailsCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
const TArray< TWeakObjectPtr<UObject> >& SelectedObjects = DetailBuilder.GetDetailsView()->GetSelectedObjects();

for (int32 ObjectIndex = 0; !MyAsset.IsValid() && ObjectIndex < SelectedObjects.Num(); ++ObjectIndex)
{
const TWeakObjectPtr<UObject>& CurrentObject = SelectedObjects[ObjectIndex];
if (CurrentObject.IsValid())
{
MyAsset = Cast<UMyCustomAsset>(CurrentObject.Get());
}
}

DetailBuilder.EditCategory("CustomCategory", FText::GetEmpty(), ECategoryPriority::Important)
.AddCustomRow(FText::GetEmpty())
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.VAlign(VAlign_Center)
[
SNew(SColorPicker)
.OnColorCommitted(this, &FMyCustomAssetDetailsCustomization::ColorPicked)
]
];
}
  1. Also, create a definition for ColorPicked:
void FMyCustomAssetDetailsCustomization::ColorPicked(FLinearColor SelectedColor)
{
if (MyAsset.IsValid())
{
MyAsset.Get()->ColorName = SelectedColor.ToFColor(false).ToHex();
}
}
  1. Beneath all of the scripts in MyCustomAssetDetailsCustomization.cpp, add the following code: 
void FMyCustomAssetPropertyDetails::CustomizeChildren(TSharedRef<IPropertyHandle> PropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils)
{
}

void FMyCustomAssetPropertyDetails::CustomizeHeader(TSharedRef<IPropertyHandle> PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils)
{
UObject* PropertyValue = nullptr;
auto GetValueResult = PropertyHandle->GetValue(PropertyValue);

HeaderRow.NameContent()
[
PropertyHandle->CreatePropertyNameWidget()
];
HeaderRow.ValueContent()
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.VAlign(VAlign_Center)
[
SNew(SColorPicker)
.OnColorCommitted(this, &FMyCustomAssetPropertyDetails::ColorPicked)
]
];
}

void FMyCustomAssetPropertyDetails::ColorPicked(FLinearColor SelectedColor)
{
if (MyAsset)
{
MyAsset->ColorName = SelectedColor.ToFColor(false).ToHex();
}
}
  1. In our editor module source file (Chapter_10Editor.cpp), add the following to your #includes in the Chapter_10Editor.cpp file:
#include "PropertyEditorModule.h" 
#include "MyCustomAssetDetailsCustomization.h"
#include "MyCustomAssetPinFactory.h"
  1. Add the following to the implementation of StartupModule:
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.RegisterCustomClassLayout(UMyCustomAsset::StaticClass()->GetFName(), FOnGetDetailCustomizationInstance::CreateStatic(&FMyCustomAssetDetailsCustomization::MakeInstance));
PropertyModule.RegisterCustomPropertyTypeLayout(UMyCustomAsset::StaticClass()->GetFName(), FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FMyCustomAssetPropertyDetails::MakeInstance));
  1. Add the following to ShutdownModule:
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.UnregisterCustomClassLayout(UMyCustomAsset::StaticClass()->GetFName());
  1. Compile your code and launch the editor. Create a new instance of MyCustomAsset via the Content Browser.
  2. Double-click on it to verify that the default editor that comes up now shows your custom layout: