void FReplaceVectorWithLinearColorBuilder::GeneratePropertyContent(const TSharedRef<IPropertyHandle>& Handle, IDetailChildrenBuilder& ChildrenBuilder)
{
	// Add to the current builder, depending on the property type.
	uint32 NumChildren = 0;
	ensure(Handle->GetNumChildren(NumChildren) == FPropertyAccess::Success);
	bool bHasChildren = (NumChildren > 0);
	bool bIsArray = Handle->AsArray().IsValid();

	if (bIsArray)
	{
		// Arrays need special handling and will create an array builder
		TSharedRef<FDetailArrayBuilder> ArrayBuilder = MakeShareable(new FDetailArrayBuilder(Handle));
		ArrayBuilder->OnGenerateArrayElementWidget(FOnGenerateArrayElementWidget::CreateSP(this, &FReplaceVectorWithLinearColorBuilder::OnGenerateArrayElementWidget));
		ChildrenBuilder.AddChildCustomBuilder(ArrayBuilder);
	}
	else if (bHasChildren)
	{
		// If there are children, we invoke a new instance of our custom builder for recursive handling
		// Note, if this is an FVector, it will be handled specially by the implementation of the IDetailCustomNodeBuilder interface.
		TSharedRef<FReplaceVectorWithLinearColorBuilder> StructBuilder = MakeShareable(new FReplaceVectorWithLinearColorBuilder(Handle));
		ChildrenBuilder.AddChildCustomBuilder(StructBuilder);
	}
	else
	{
		// No children - just add the property.
		ChildrenBuilder.AddChildProperty(Handle);
	}
}
void FRawDistributionVectorStructCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> StructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
	// Determine from the metadata whether we should treat vectors as FLinearColors or not
	bool bTreatAsColor = StructPropertyHandle->HasMetaData("TreatAsColor");

	uint32 NumChildren;
	ensure(StructPropertyHandle->GetNumChildren(NumChildren) == FPropertyAccess::Success);

	// Now recurse through all children, creating a custom builder for each which will either add the default property row, or
	// a property row exposing a FLinearColor type customization which maps directly to the elements of the original FVector.
	for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ChildIndex++)
	{
		TSharedPtr<IPropertyHandle> ChildHandle = StructPropertyHandle->GetChildHandle(ChildIndex);
		check(ChildHandle.IsValid());
		if (bTreatAsColor)
		{
			TSharedRef<FReplaceVectorWithLinearColorBuilder> CustomBuilder = MakeShareable(new FReplaceVectorWithLinearColorBuilder(ChildHandle.ToSharedRef()));
			StructBuilder.AddChildCustomBuilder(CustomBuilder);
		}
		else
		{
			StructBuilder.AddChildProperty(ChildHandle.ToSharedRef());
		}
	}
}
void FLandscapeEditorStructCustomization_FGizmoImportLayer::CustomizeChildren(TSharedRef<IPropertyHandle> StructPropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
	TSharedRef<IPropertyHandle> PropertyHandle_LayerFilename = StructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FGizmoImportLayer, LayerFilename)).ToSharedRef();
	ChildBuilder.AddChildProperty(PropertyHandle_LayerFilename)
	.CustomWidget()
	.NameContent()
	[
		PropertyHandle_LayerFilename->CreatePropertyNameWidget()
	]
	.ValueContent()
	.MinDesiredWidth(250.0f)
	.MaxDesiredWidth(0)
	[
		SNew(SHorizontalBox)
		+ SHorizontalBox::Slot()
		[
			PropertyHandle_LayerFilename->CreatePropertyValueWidget()
		]
		+ SHorizontalBox::Slot()
		.AutoWidth()
		//.Padding(0,0,12,0) // Line up with the other properties due to having no reset to default button
		[
			SNew(SButton)
			.ContentPadding(FMargin(4, 0))
			.Text(NSLOCTEXT("UnrealEd", "GenericOpenDialog", "..."))
			.OnClicked_Static(&FLandscapeEditorStructCustomization_FGizmoImportLayer::OnGizmoImportLayerFilenameButtonClicked, PropertyHandle_LayerFilename)
		]
	];

	TSharedRef<IPropertyHandle> PropertyHandle_LayerName = StructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FGizmoImportLayer, LayerName)).ToSharedRef();
	ChildBuilder.AddChildProperty(PropertyHandle_LayerName);
}
void FReplaceVectorWithLinearColorBuilder::AddColorChildProperty(const TSharedPtr<IPropertyHandle>& StructHandle, const FText& Text, int32 ElementIndex, IDetailChildrenBuilder& ChildrenBuilder)
{
	ChildrenBuilder.AddChildContent(LOCTEXT("Color", "Color"))
		.NameContent()
		[
			SNew(STextBlock)
			.Text(Text)
			.Font(IPropertyTypeCustomizationUtils::GetRegularFont())
		]
	.ValueContent()
		.MinDesiredWidth(100.0f)
		.MaxDesiredWidth(100.0f)
		[
			SNew(SNumericEntryBox<float>)
			.Font(IPropertyTypeCustomizationUtils::GetRegularFont())
			.Value(this, &FReplaceVectorWithLinearColorBuilder::OnGetColorElementValue, StructHandle, ElementIndex)
			.OnValueCommitted(this, &FReplaceVectorWithLinearColorBuilder::OnColorElementValueCommitted, StructHandle, ElementIndex)
			.OnValueChanged(this, &FReplaceVectorWithLinearColorBuilder::OnColorElementValueChanged, StructHandle, ElementIndex)
			.OnBeginSliderMovement(this, &FReplaceVectorWithLinearColorBuilder::OnBeginSliderMovement)
			.OnEndSliderMovement(this, &FReplaceVectorWithLinearColorBuilder::OnEndSliderMovement)
			.AllowSpin(true)
			.MinSliderValue(0.0f)
			.MaxSliderValue(1.0f)
		];
}
void FActionMappingsNodeBuilder::GenerateChildContent( IDetailChildrenBuilder& ChildrenBuilder )
{
	RebuildGroupedMappings();

	for (int32 Index = 0; Index < GroupedMappings.Num(); ++Index)
	{
		FMappingSet& MappingSet = GroupedMappings[Index];

		FString GroupNameString(TEXT("ActionMappings."));
		MappingSet.SharedName.AppendString(GroupNameString);
		FName GroupName(*GroupNameString);
		IDetailGroup& ActionMappingGroup = ChildrenBuilder.AddChildGroup(GroupName, FText::FromName(MappingSet.SharedName));
		MappingSet.DetailGroup = &ActionMappingGroup;

		TSharedRef<SWidget> AddButton = PropertyCustomizationHelpers::MakeAddButton(FSimpleDelegate::CreateSP(this, &FActionMappingsNodeBuilder::AddActionMappingToGroupButton_OnClick, MappingSet),
			LOCTEXT("AddActionMappingToGroupToolTip", "Adds Action Mapping to Group"));

		TSharedRef<SWidget> RemoveButton = PropertyCustomizationHelpers::MakeDeleteButton(FSimpleDelegate::CreateSP(this, &FActionMappingsNodeBuilder::RemoveActionMappingGroupButton_OnClick, MappingSet),
			LOCTEXT("RemoveActionMappingGroupToolTip", "Removes Action Mapping Group"));

		ActionMappingGroup.HeaderRow()
		[
			SNew( SHorizontalBox )
			+ SHorizontalBox::Slot()
			.AutoWidth()
			[
				SNew(SBox)
				.WidthOverride( InputConstants::TextBoxWidth )
				[
					SNew(SEditableTextBox)
					.Padding(2.0f)
					.Text(FText::FromName(MappingSet.SharedName))
					.OnTextCommitted(FOnTextCommitted::CreateSP(this, &FActionMappingsNodeBuilder::OnActionMappingNameCommitted, MappingSet))
					.Font(IDetailLayoutBuilder::GetDetailFont())
				]
			]
			+SHorizontalBox::Slot()
			.Padding(InputConstants::PropertyPadding)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			.AutoWidth()
			[
				AddButton
			]
			+SHorizontalBox::Slot()
			.Padding(InputConstants::PropertyPadding)
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			.AutoWidth()
			[
				RemoveButton
			]
		];
	
		for (int32 MappingIndex = 0; MappingIndex < MappingSet.Mappings.Num(); ++MappingIndex)
		{
			ActionMappingGroup.AddPropertyRow(MappingSet.Mappings[MappingIndex]).ShowPropertyButtons(false);
		}
	}
}
void FSpriteDetailsCustomization::GenerateAdditionalTextureWidget(TSharedRef<IPropertyHandle> PropertyHandle, int32 ArrayIndex, IDetailChildrenBuilder& ChildrenBuilder)
{
	IDetailPropertyRow& TextureRow = ChildrenBuilder.AddChildProperty(PropertyHandle);

	FText ExtraText;
	if (FText* pExtraText = AdditionalTextureLabels.Find(ArrayIndex))
	{
		ExtraText = *pExtraText;
	}

	FNumberFormattingOptions NoCommas;
	NoCommas.UseGrouping = false;
	const FText SlotDesc = FText::Format(LOCTEXT("AdditionalTextureSlotIndex", "Slot #{0}"), FText::AsNumber(ArrayIndex, &NoCommas));

	TextureRow.DisplayName(SlotDesc);

	TextureRow.ShowPropertyButtons(false);

	TextureRow.CustomWidget(false)
		.NameContent()
		[
			CreateTextureNameWidget(PropertyHandle, ExtraText)
		]
		.ValueContent()
		.MaxDesiredWidth(TOptional<float>())
		[
			PropertyHandle->CreatePropertyValueWidget()
		];
}
void FMoviePlayerSettingsDetails::GenerateArrayElementWidget(TSharedRef<IPropertyHandle> PropertyHandle, int32 ArrayIndex, IDetailChildrenBuilder& ChildrenBuilder)
{
	IDetailPropertyRow& FilePathRow = ChildrenBuilder.AddChildProperty( PropertyHandle );
	{
		FilePathRow.CustomWidget(false)
			.NameContent()
			[
				PropertyHandle->CreatePropertyNameWidget()
			]
			.ValueContent()
			.MaxDesiredWidth(0.0f)
			.MinDesiredWidth(125.0f)
			[
				SNew(SFilePathPicker)
					.BrowseButtonImage(FEditorStyle::GetBrush("PropertyWindow.Button_Ellipsis"))
					.BrowseButtonStyle(FEditorStyle::Get(), "HoverHintOnly")
					.BrowseButtonToolTip(LOCTEXT("FileButtonToolTipText", "Choose a file from this computer"))
					.BrowseDirectory(FEditorDirectories::Get().GetLastDirectory(ELastDirectory::GENERIC_OPEN))
					.BrowseTitle(LOCTEXT("PropertyEditorTitle", "File picker..."))
					.FilePath(this, &FMoviePlayerSettingsDetails::HandleFilePathPickerFilePath, PropertyHandle)
					.FileTypeFilter(TEXT("MPEG-4 Movie (*.mp4)|*.mp4"))
					.OnPathPicked(this, &FMoviePlayerSettingsDetails::HandleFilePathPickerPathPicked, PropertyHandle)
			];
	}
};
Example #8
0
void FDialogueContextMappingNodeBuilder::GenerateChildContent( IDetailChildrenBuilder& ChildrenBuilder )
{
	if( ContextMappingPropertyHandle->IsValidHandle() )
	{
		const TSharedPtr<IPropertyHandle> SoundwavePropertyHandle = ContextMappingPropertyHandle->GetChildHandle("Soundwave");
		ChildrenBuilder.AddChildProperty(SoundwavePropertyHandle.ToSharedRef());
	}
}
void FFormatTextLayout::GenerateChildContent( IDetailChildrenBuilder& ChildrenBuilder )
{
	Children.Empty();
	for (int32 ArgIdx = 0; ArgIdx < TargetNode->GetArgumentCount(); ++ArgIdx)
	{
		TSharedRef<class FFormatTextArgumentLayout> ArgumentIndexLayout = MakeShareable(new FFormatTextArgumentLayout(TargetNode, ArgIdx) );
		ChildrenBuilder.AddChildCustomBuilder(ArgumentIndexLayout);
		Children.Add(ArgumentIndexLayout);
	}
}
void FNiagaraEmitterPropertiesDetails::OnGenerateScalarConstantEntry(TSharedRef<IPropertyHandle> ElementProperty, int32 ElementIndex, IDetailChildrenBuilder& ChildrenBuilder)
{
	TSharedPtr<IPropertyHandle> ValueProperty = ElementProperty->GetChildHandle(GET_MEMBER_NAME_CHECKED(FNiagaraConstants_Float, Value));
	TSharedPtr<IPropertyHandle> NameProperty = ElementProperty->GetChildHandle(GET_MEMBER_NAME_CHECKED(FNiagaraConstants_Float, Name));

	FName DisplayName;
	NameProperty->GetValue(DisplayName);
	//Don't display system constants
	if (UNiagaraComponent::GetSystemConstants().Find(FNiagaraVariableInfo(DisplayName, ENiagaraDataType::Scalar)) == INDEX_NONE)
	{
		ChildrenBuilder.AddChildProperty(ValueProperty.ToSharedRef()).DisplayName(FText::FromName(DisplayName));
	}
}
void FLightmapCustomNodeBuilder::GenerateChildContent(IDetailChildrenBuilder& ChildrenBuilder)
{
	RefreshLightmapItems();

	for(TSharedPtr<FLightmapItem>& Item : LightmapItems)
	{
		ChildrenBuilder.AddChildContent(LOCTEXT("LightMapsFilter", "Lightmaps"))
		.ValueContent()
		.HAlign(HAlign_Fill)
		[
			MakeLightMapList(Item)
		];
	}
}
void FLightmapCustomNodeBuilder::GenerateChildContent(IDetailChildrenBuilder& ChildrenBuilder)
{
	RefreshLightmapItems();

	ChildrenBuilder.AddChildContent(LOCTEXT("LightMapsFilter", "Lightmaps"))
	.ValueContent()
	.HAlign(HAlign_Fill)
	[
		SAssignNew(LightmapListView, SListView<TSharedPtr<FLightmapItem>>)
		.ListItemsSource(&LightmapItems)
		.OnGenerateRow(this, &FLightmapCustomNodeBuilder::MakeLightMapListViewWidget)
		.OnContextMenuOpening(this, &FLightmapCustomNodeBuilder::OnGetLightMapContextMenuContent)
		.OnMouseButtonDoubleClick(this, &FLightmapCustomNodeBuilder::OnLightMapListMouseButtonDoubleClick)
	];
}
void FAbcCompressionSettingsCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> StructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
	Settings = UAbcImportSettings::Get();

	uint32 NumChildren;
	StructPropertyHandle->GetNumChildren(NumChildren);

	for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex)
	{
		TSharedRef<IPropertyHandle> ChildHandle = StructPropertyHandle->GetChildHandle(ChildIndex).ToSharedRef();
		IDetailPropertyRow& Property = StructBuilder.AddChildProperty(ChildHandle);
		static const FName EditConditionName = "EnumCondition";
		int32 EnumCondition = ChildHandle->GetINTMetaData(EditConditionName);
		Property.Visibility(TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FAbcCompressionSettingsCustomization::ArePropertiesVisible, EnumCondition)));
	}
}
void FWidgetNavigationCustomization::MakeNavRow(TWeakPtr<IPropertyHandle> PropertyHandle, IDetailChildrenBuilder& ChildBuilder, EUINavigation Nav, FText NavName)
{
	ChildBuilder.AddChildContent(NavName)
		.NameContent()
		[
			SNew(STextBlock)
			.Font(IDetailLayoutBuilder::GetDetailFont())
			.Text(NavName)
		]
		.ValueContent()
		.MaxDesiredWidth(300)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
			.AutoWidth()
			[
				SNew(SComboButton)
				.HAlign(HAlign_Center)
				.ButtonContent()
				[
					SNew(STextBlock)
					.Text(this, &FWidgetNavigationCustomization::GetNavigationText, PropertyHandle, Nav)
				]
				.ContentPadding(FMargin(2.0f, 1.0f))
				.MenuContent()
				[
					MakeNavMenu(PropertyHandle, Nav)
				]
			]

			// Explicit Navigation Widget
			+ SHorizontalBox::Slot()
			.FillWidth(1.0f)
			[
				SNew(SEditableTextBox)
				.HintText(LOCTEXT("WidgetName", "Widget Name?"))
				.Text(this, &FWidgetNavigationCustomization::GetExplictWidget, PropertyHandle, Nav)
				.OnTextCommitted(this, &FWidgetNavigationCustomization::OnCommitExplictWidgetText, PropertyHandle, Nav)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.Visibility(this, &FWidgetNavigationCustomization::GetExplictWidgetFieldVisibility, PropertyHandle, Nav)
			]
		];
}
void FNiagaraEmitterPropertiesDetails::OnGenerateEventReceiverEntry(TSharedRef<IPropertyHandle> ElementProperty, int32 ElementIndex, IDetailChildrenBuilder& ChildrenBuilder)
{
	TSharedPtr<IPropertyHandle> NameProperty = ElementProperty->GetChildHandle(GET_MEMBER_NAME_CHECKED(FNiagaraEventReceiverProperties, Name));

 	FName DisplayName;
 	NameProperty->GetValue(DisplayName);
// 	ChildrenBuilder.AddChildProperty(ElementProperty).DisplayName(FText::FromName(DisplayName));

	IDetailGroup& Group = ChildrenBuilder.AddChildGroup(DisplayName, FText::FromName(DisplayName));
	uint32 NumChildren = 0;
	if (ElementProperty->GetNumChildren(NumChildren) == FPropertyAccess::Success)
	{
		for (uint32 i = 0; i < NumChildren; ++i)
		{
			TSharedPtr<IPropertyHandle> Child = ElementProperty->GetChildHandle(i);
			//Dont add the ID. We just grab it's name for the name region of this property.
			if (Child.IsValid() && Child->GetProperty()->GetName() != GET_MEMBER_NAME_CHECKED(FNiagaraEventReceiverProperties, Name).ToString())
			{
				TSharedPtr<SWidget> NameWidget;
				TSharedPtr<SWidget> ValueWidget;
				FDetailWidgetRow DefaultDetailRow;
			
				IDetailPropertyRow& Row = Group.AddPropertyRow(Child.ToSharedRef());
				Row.GetDefaultWidgets(NameWidget, ValueWidget, DefaultDetailRow);
				Row.CustomWidget(true)
					.NameContent()
					[
						NameWidget.ToSharedRef()
					]
					.ValueContent()
					[
						ValueWidget.ToSharedRef()
					];
			}
		}
	}
}
void FNiagaraEmitterPropertiesDetails::OnGenerateEventGeneratorEntry(TSharedRef<IPropertyHandle> ElementProperty, int32 ElementIndex, IDetailChildrenBuilder& ChildrenBuilder)
{
	TSharedPtr<IPropertyHandle> IDProperty = ElementProperty->GetChildHandle(GET_MEMBER_NAME_CHECKED(FNiagaraEventGeneratorProperties, ID));
	TSharedPtr<IPropertyHandle> NameProperty = IDProperty->GetChildHandle(GET_MEMBER_NAME_CHECKED(FNiagaraDataSetID, Name));

	FName DisplayName;
	NameProperty->GetValue(DisplayName);
	//IDetailPropertyRow& Row = ChildrenBuilder.AddChildProperty(ElementProperty).DisplayName(FText::FromName(DisplayName));

	IDetailGroup& GenGroup = ChildrenBuilder.AddChildGroup(DisplayName, FText::FromName(DisplayName));
	uint32 NumChildren = 0;
	if (ElementProperty->GetNumChildren(NumChildren) == FPropertyAccess::Success)
	{
		for (uint32 i = 0; i < NumChildren; ++i)
		{
			TSharedPtr<IPropertyHandle> Child = ElementProperty->GetChildHandle(i);
			//Dont add the ID. We just grab it's name for the name region of this property.
			if (Child.IsValid() && Child->GetProperty()->GetName() != GET_MEMBER_NAME_CHECKED(FNiagaraEventGeneratorProperties, ID).ToString())
			{
				GenGroup.AddPropertyRow(Child.ToSharedRef());
			}
		}
	}
}
void FAttributeBasedFloatDetails::CustomizeChildren(TSharedRef<IPropertyHandle> StructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
	uint32 NumChildrenProps = 0;
	StructPropertyHandle->GetNumChildren(NumChildrenProps);

	AttributeCalculationTypePropertyHandle = StructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FAttributeBasedFloat, AttributeCalculationType));
	const TSharedPtr<IPropertyHandle> FinalChannelHandle = StructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FAttributeBasedFloat, FinalChannel));
	
	if (ensure(FinalChannelHandle.IsValid()) && ensure(FinalChannelHandle->IsValidHandle()) && ensure(AttributeCalculationTypePropertyHandle.IsValid()) && ensure(AttributeCalculationTypePropertyHandle->IsValidHandle()))
	{
		for (uint32 ChildIdx = 0; ChildIdx < NumChildrenProps; ++ChildIdx)
		{
			TSharedPtr<IPropertyHandle> ChildHandle = StructPropertyHandle->GetChildHandle(ChildIdx);
			if (ChildHandle.IsValid() && ChildHandle->IsValidHandle())
			{
				IDetailPropertyRow& NewPropRow = StructBuilder.AddChildProperty(ChildHandle.ToSharedRef());
				if (ChildHandle->GetProperty() == FinalChannelHandle->GetProperty())
				{
					NewPropRow.Visibility(TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FAttributeBasedFloatDetails::GetFinalChannelVisibility)));
				}
			}
		}
	}
}
void FVehicleTransmissionDataCustomization::CreateGearUIDelegate(TSharedRef<IPropertyHandle> GearProperty, int32 GearIdx, IDetailChildrenBuilder& ChildrenBuilder)
{
	FText Label = FText::Format(LOCTEXT("TransmissionGear", "Gear {0}"), FText::AsNumber(GearIdx + 1));
	CreateGearUIHelper(ChildrenBuilder.AddChildContent(Label), Label, GearProperty, ForwardGear);
}
void FCurveColorCustomization::CustomizeChildren(TSharedRef<IPropertyHandle> InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
	uint32 NumChildren = 0;
	StructPropertyHandle->GetNumChildren(NumChildren);

	for( uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex )
	{
		TSharedPtr<IPropertyHandle> Child = StructPropertyHandle->GetChildHandle( ChildIndex );

		if( Child->GetProperty()->GetName() == TEXT("ExternalCurve") )
		{
			ExternalCurveHandle = Child;

			FSimpleDelegate OnCurveChangedDelegate = FSimpleDelegate::CreateSP( this, &FCurveColorCustomization::OnExternalCurveChanged, InStructPropertyHandle );
			Child->SetOnPropertyValueChanged(OnCurveChangedDelegate);

			StructBuilder.AddChildContent(LOCTEXT("ExternalCurveLabel", "ExternalCurve"))
				.NameContent()
				[
					Child->CreatePropertyNameWidget()
				]
				.ValueContent()
				[
					SNew(SVerticalBox)
					+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(SHorizontalBox)
						+SHorizontalBox::Slot()
						[
							Child->CreatePropertyValueWidget()
						]
						+SHorizontalBox::Slot()
						.AutoWidth()
						.VAlign(VAlign_Center)
						.Padding(1,0)
						[
							SNew(SButton)
							.ButtonStyle( FEditorStyle::Get(), "NoBorder" )
							.ContentPadding(1.f)
							.ToolTipText(LOCTEXT("ConvertInternalCurveTooltip", "Convert to Internal Color Curve"))
							.OnClicked(this, &FCurveColorCustomization::OnConvertButtonClicked)
							.IsEnabled(this, &FCurveColorCustomization::IsConvertButtonEnabled)
							[
								SNew(SImage)
								.Image( FEditorStyle::GetBrush(TEXT("PropertyWindow.Button_Clear")) )
							]
						]
					]
					+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(SButton)
						.HAlign(HAlign_Center)
						.Text( LOCTEXT( "CreateAssetButton", "Create External Curve" ) )
						.ToolTipText(LOCTEXT( "CreateAssetTooltip", "Create a new Color Curve asset from this curve") )
						.OnClicked(this, &FCurveColorCustomization::OnCreateButtonClicked)
						.IsEnabled(this, &FCurveColorCustomization::IsCreateButtonEnabled)
					]
				];
		}
		else
		{
			StructBuilder.AddChildProperty(Child.ToSharedRef());
		}
	}
}
void FAssetImportDataCustomization::CustomizeChildren( TSharedRef<IPropertyHandle> InPropertyHandle, IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& CustomizationUtils )
{
	PropertyHandle = InPropertyHandle;

	FAssetImportInfo* Info = GetEditStruct();
	if (!Info)
	{
		return;
	}

	auto Font = IDetailLayoutBuilder::GetDetailFont();

	const FText SourceFileText = LOCTEXT("SourceFile", "Source File");
	for (int32 Index = 0; Index < Info->SourceFiles.Num(); ++Index)
	{
		ChildBuilder.AddChildContent(SourceFileText)
		.NameContent()
		[
			SNew(STextBlock)
			.Text(SourceFileText)
			.Font(Font)
		]
		.ValueContent()
		.HAlign(HAlign_Fill)
		.MaxDesiredWidth(TOptional<float>())
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
			.AutoHeight()
			[
				SNew(SHorizontalBox)

				+ SHorizontalBox::Slot()
				[
					SNew(SEditableText)
					.IsReadOnly(true)
					.Text(this, &FAssetImportDataCustomization::GetFilenameText, Index)
					.ToolTipText(this, &FAssetImportDataCustomization::GetFilenameText, Index)
					.Font(Font)
				]

				+SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SButton)
					.OnClicked(this, &FAssetImportDataCustomization::OnChangePathClicked, Index)
					.ToolTipText(LOCTEXT("ChangePath_Tooltip", "Browse for a new source file path"))
					[
						SNew(STextBlock)
						.Text(LOCTEXT("...", "..."))
						.Font(Font)
					]
				]

				+SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SButton)
					.VAlign(VAlign_Center)
					.HAlign(HAlign_Center)
					.ButtonStyle(FEditorStyle::Get(), "HoverHintOnly")
					.OnClicked(this, &FAssetImportDataCustomization::OnClearPathClicked, Index)
					.ToolTipText(LOCTEXT("ClearPath_Tooltip", "Clear this source file information from the asset"))
					[
						SNew(SImage)
						.Image(FEditorStyle::GetBrush("Cross"))
					]
				]
			]

			+ SVerticalBox::Slot()
			.AutoHeight()
			[
				SNew(SEditableText)
				.IsReadOnly(true)
				.Text(this, &FAssetImportDataCustomization::GetTimestampText, Index)
				.Font(Font)
			]
		];
	}
}
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void FTextureLODGroupLayout::GenerateChildContent(IDetailChildrenBuilder& ChildrenBuilder)
{
	// Min and Max LOD properties
	{
		ChildrenBuilder.AddChildContent(LOCTEXT("MinLODSize", "Min LOD Size"))
			.NameContent()
			[
				SNew(STextBlock)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.Text(LOCTEXT("MinLODSize", "Min LOD Size"))
			]
			.ValueContent()
			[
				SNew(SSpinBox<uint32>)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.MinValue(2)
				.MaxValue(4096)
				.Value(this, &FTextureLODGroupLayout::GetMinLODSize)
				.OnValueChanged(this, &FTextureLODGroupLayout::OnMinLODSizeChanged)
				.OnValueCommitted(this, &FTextureLODGroupLayout::OnMinLODSizeCommitted)
			];
	}

	{
		ChildrenBuilder.AddChildContent(LOCTEXT("MaxLODSize", "Max LOD Size"))
			.NameContent()
			[
				SNew(STextBlock)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.Text(LOCTEXT("MaxLODSize", "Max LOD Size"))
			]
			.ValueContent()
			[
				SNew(SSpinBox<uint32>)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.MinValue(2)
				.MaxValue(4096)
				.Value(this, &FTextureLODGroupLayout::GetMaxLODSize)
				.OnValueChanged(this, &FTextureLODGroupLayout::OnMaxLODSizeChanged)
				.OnValueCommitted(this, &FTextureLODGroupLayout::OnMaxLODSizeCommitted)
			];
	}


	// LOD Bias
	{
		ChildrenBuilder.AddChildContent(LOCTEXT("LODBias", "LOD Bias"))
			.NameContent()
			[
				SNew(STextBlock)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.Text(LOCTEXT("LODBias", "LOD Bias"))
			]
			.ValueContent()
			[
				SNew(SSpinBox<uint32>)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.MinValue(1)
				.MaxValue(100)
				.Value(this, &FTextureLODGroupLayout::GetLODBias)
				.OnValueChanged(this, &FTextureLODGroupLayout::OnLODBiasChanged)
				.OnValueCommitted(this, &FTextureLODGroupLayout::OnLODBiasCommitted)
			];
	}


	// Filter properties

	TSharedPtr<FName> NamePointPtr = MakeShareable(new FName(NAME_Point));
	FilterComboList.Add(NamePointPtr);
	TSharedPtr<FName> NameLinearPtr = MakeShareable(new FName(NAME_Linear));
	FilterComboList.Add(NameLinearPtr);
	TSharedPtr<FName> NameAnisoPtr = MakeShareable(new FName(NAME_Aniso));
	FilterComboList.Add(NameAnisoPtr);
	{
		ChildrenBuilder.AddChildContent(LOCTEXT("MinMagFilter", "MinMag Filter"))
			.NameContent()
			[
				SNew(STextBlock)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.Text(LOCTEXT("MinMagFilter", "MinMag Filter"))
			]
			.ValueContent()
			[
				SNew(SComboBox< TSharedPtr<FName> >)
				.OptionsSource(&FilterComboList)
				.OnGenerateWidget(this, &FTextureLODGroupLayout::MakeMinMagFilterComboWidget)
				.OnSelectionChanged(this, &FTextureLODGroupLayout::OnMinMagFilterChanged)
				.InitiallySelectedItem(FilterComboList[0])
				.ContentPadding(0)
				.Content()
				[
					SNew(STextBlock)
					.Text(this, &FTextureLODGroupLayout::GetMinMagFilterComboBoxContent)
					.Font(IDetailLayoutBuilder::GetDetailFont())
					.ToolTipText(this, &FTextureLODGroupLayout::GetMinMagFilterComboBoxToolTip)
				]
			];
	}

	{
		ChildrenBuilder.AddChildContent(LOCTEXT("MipFilter", "Mip Filter"))
			.NameContent()
			[
				SNew(STextBlock)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.Text(LOCTEXT("MipFilter", "Mip Filter"))
			]
		.ValueContent()
			[
				SNew(SComboBox< TSharedPtr<FName> >)
				.OptionsSource(&FilterComboList)
				.OnGenerateWidget(this, &FTextureLODGroupLayout::MakeMipFilterComboWidget)
				.OnSelectionChanged(this, &FTextureLODGroupLayout::OnMipFilterChanged)
				.InitiallySelectedItem(FilterComboList[0])
				.ContentPadding(0)
				.Content()
				[
					SNew(STextBlock)
					.Text(this, &FTextureLODGroupLayout::GetMipFilterComboBoxContent)
					.Font(IDetailLayoutBuilder::GetDetailFont())
					.ToolTipText(this, &FTextureLODGroupLayout::GetMipFilterComboBoxToolTip)
				]
			];
	}


	// Mip Gen Settings
	{
		ChildrenBuilder.AddChildContent(LOCTEXT("MipGenSettings", "Mip Gen Settings"))
			.NameContent()
			[
				SNew(STextBlock)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.Text(LOCTEXT("MipGenSettings", "Mip Gen Settings"))
			]
		.ValueContent()
			[
				SNew(SComboBox< TSharedPtr<TextureMipGenSettings> >)
				.OptionsSource(&MipGenSettingsComboList)
				.OnGenerateWidget(this, &FTextureLODGroupLayout::MakeMipGenSettingsComboWidget)
				.OnSelectionChanged(this, &FTextureLODGroupLayout::OnMipGenSettingsChanged)
				.InitiallySelectedItem(MipGenSettingsComboList[0])
				.ContentPadding(0)
				.Content()
				[
					SNew(STextBlock)
					.Text(this, &FTextureLODGroupLayout::GetMipGenSettingsComboBoxContent)
					.Font(IDetailLayoutBuilder::GetDetailFont())
					.ToolTipText(this, &FTextureLODGroupLayout::GetMipGenSettingsComboBoxToolTip)
				]
			];
	}

}
void FRemeshingSettingsLayout::GenerateChildContent( IDetailChildrenBuilder& ChildrenBuilder )
{
	//Use MassiveLOD
	ChildrenBuilder.AddChildContent(LOCTEXT("UseMassiveLOD", "Use MassiveLOD") )
		.Visibility(RemeshingSettingsVisisbility)
		.NameContent()
		[
			SNew( STextBlock )
			.Font( IDetailLayoutBuilder::GetDetailFont() )
			.Text( LOCTEXT("AsParent", "As Parent") )
		]
	.ValueContent()
		[
			SNew(SCheckBox)
			.IsChecked(this, &FRemeshingSettingsLayout::GetUseMassiveLODState)
			.OnCheckStateChanged(this, &FRemeshingSettingsLayout::OnUseMassiveLODChanged)
		];

	//Size On Screen
	ChildrenBuilder.AddChildContent( LOCTEXT("SizeOnScreen", "Size On Screen") )
		.Visibility(RemeshingSettingsVisisbility)
		.NameContent()
		[
			SNew( STextBlock )
			.Font( IDetailLayoutBuilder::GetDetailFont() )
			.Text( LOCTEXT("SizeOnScreen", "Size On Screen") )
		]
	.ValueContent()
		[
			SNew(SSpinBox<int32>)
			.Font( IDetailLayoutBuilder::GetDetailFont() )
			.MinValue(1)
			.MaxValue(5000)
			.Value(this, &FRemeshingSettingsLayout::GetSizeOnScreen)
			.OnValueChanged(this, &FRemeshingSettingsLayout::OnSizeOnScreenChanged)
			.OnValueCommitted(this, &FRemeshingSettingsLayout::OnSizeOnScreenCommitted)
		];

	//Merge Distance
	ChildrenBuilder.AddChildContent( LOCTEXT("MergeDistance", "Merge Distance") )
		.Visibility(RemeshingSettingsVisisbility)
		.NameContent()
		[
			SNew( STextBlock )
			.Font( IDetailLayoutBuilder::GetDetailFont() )
			.Text( LOCTEXT("MergeDistance", "Merge Distance") )
		]
	.ValueContent()
		[
			SNew(SSpinBox<int32>)
			.Font( IDetailLayoutBuilder::GetDetailFont() )
			.MinValue(0)
			.MaxValue(5000)
			.Value(this, &FRemeshingSettingsLayout::GetMergeDistance)
			.OnValueChanged(this, &FRemeshingSettingsLayout::OnMergeDistanceChanged)
			.OnValueCommitted(this, &FRemeshingSettingsLayout::OnMergeDistanceCommitted)
		];

	//Recalculate Normals
	/*ChildrenBuilder.AddChildContent( LOCTEXT("RecalculateNormals", "Recalculate Normals") )
		.Visibility(RemeshingSettingsVisisbility)
		.NameContent()
		[
		SNew( STextBlock )
		.Font( IDetailLayoutBuilder::GetDetailFontBold() )
		.Text( LOCTEXT("RecalculateNormals", "Recalculate Normals").ToString() )
		];*/

		ChildrenBuilder.AddChildContent( LOCTEXT("HardAngle", "Hard Angle") )
		.Visibility(RemeshingSettingsVisisbility)

		.NameContent()
		[
			SNew(SBox)
			.Content()
			[
				SNew( STextBlock )
				.Font( IDetailLayoutBuilder::GetDetailFont() )
				.Text( LOCTEXT("HardAngle", "Hard Angle") )
			]
		]
	.ValueContent()
		[
			SNew(SSpinBox<float>)
			.Font( IDetailLayoutBuilder::GetDetailFont() )
			.MinValue(0.0f)
			.MaxValue(180.0f)
			.Value(this, &FRemeshingSettingsLayout::GetHardAngle)
			.OnValueChanged(this, &FRemeshingSettingsLayout::OnHardAngleChanged)
			.OnValueCommitted(this, &FRemeshingSettingsLayout::OnHardAngleCommitted)
		];
}