void FReplaceVectorWithLinearColorBuilder::GenerateHeaderRowContent(FDetailWidgetRow& NodeRow)
{
	// Only generate a header row if the handle has a valid UProperty.
	// Note that it's possible for the Property to be NULL if the property node is an FObjectPropertyNode - however we still want to create children in this case.
	if (PropertyHandle->GetProperty() != nullptr)
	{
		NodeRow.NameContent()
			[
				PropertyHandle->CreatePropertyNameWidget()
			];

		if (bIsVectorProperty)
		{
			// Customization - make FVector look like an FLinearColor
			NodeRow.ValueContent()
				.MinDesiredWidth(250.0f)
				.MaxDesiredWidth(250.0f)
				[
					CreateColorWidget(PropertyHandle)
				];
		}
		else
		{
			// Otherwise, use the default property widget
			NodeRow.ValueContent()
				.MinDesiredWidth(1)
				.MaxDesiredWidth(4096)
				[
					PropertyHandle->CreatePropertyValueWidget()
				];
		}
	}
}
void FLightmapCustomNodeBuilder::GenerateHeaderRowContent(FDetailWidgetRow& NodeRow)
{
	NodeRow.NameContent()
	[
		SNew( STextBlock )
		.Text( LOCTEXT("LightmapHeaderRowContent", "Lightmaps") )
		.Font( IDetailLayoutBuilder::GetDetailFont() )
	];

	NodeRow.ValueContent()
	[
		SNew( STextBlock )
		.Text( this, &FLightmapCustomNodeBuilder::GetLightmapCountText )
		.Font( IDetailLayoutBuilder::GetDetailFont() )
	];
}
void FMathStructCustomization::MakeHeaderRow( TSharedRef<class IPropertyHandle>& StructPropertyHandle, FDetailWidgetRow& Row )
{
	// We'll set up reset to default ourselves
	const bool bDisplayResetToDefault = false;
	const FString DisplayNameOverride = TEXT("");

	TSharedPtr<SHorizontalBox> HorizontalBox;

	Row.NameContent()
	[
		StructPropertyHandle->CreatePropertyNameWidget( DisplayNameOverride, bDisplayResetToDefault )
	]
	.ValueContent()
	// Make enough space for each child handle
	.MinDesiredWidth(125.0f * SortedChildHandles.Num() )
	.MaxDesiredWidth(125.0f * SortedChildHandles.Num() )
	[
		SAssignNew( HorizontalBox, SHorizontalBox )
	];

	for( int32 ChildIndex = 0; ChildIndex < SortedChildHandles.Num(); ++ChildIndex )
	{
		TSharedRef<IPropertyHandle> ChildHandle = SortedChildHandles[ChildIndex];

		const bool bLastChild = SortedChildHandles.Num()-1 == ChildIndex;
		// Make a widget for each property.  The vector component properties  will be displayed in the header

		HorizontalBox->AddSlot()
		.Padding( FMargin(0.0f, 2.0f, bLastChild ? 0.0f : 3.0f, 2.0f ) )
		[
			MakeChildWidget( ChildHandle )
		];
	}
}
void FColorStructCustomization::MakeHeaderRow( TSharedRef<class IPropertyHandle>& InStructPropertyHandle, FDetailWidgetRow& Row )
{
	// We'll set up reset to default ourselves
	const bool bDisplayResetToDefault = false;
	const FString DisplayNameOverride = TEXT("");

	FSlateFontInfo NormalText = IDetailLayoutBuilder::GetDetailFont();

	Row.NameContent()
	[
		StructPropertyHandle->CreatePropertyNameWidget( DisplayNameOverride, bDisplayResetToDefault )
	]
	.ValueContent()
	.MinDesiredWidth(250.0f)
	.MaxDesiredWidth(250.0f)
	[
		SNew( SHorizontalBox )
		+ SHorizontalBox::Slot()
		.VAlign(VAlign_Center)
		[
			SNew( SOverlay )
			+SOverlay::Slot()
			[
				// Displays the color with alpha unless it is ignored
				SAssignNew( ColorPickerParentWidget, SColorBlock )
				.Color( this, &FColorStructCustomization::OnGetColorForColorBlock )
				.ShowBackgroundForAlpha(true)
				.IgnoreAlpha( bIgnoreAlpha )
				.OnMouseButtonDown( this, &FColorStructCustomization::OnMouseButtonDownColorBlock )
				.Size( FVector2D( 35.0f, 12.0f ) )
			]
			+SOverlay::Slot()
			.HAlign(HAlign_Center)
			.VAlign(VAlign_Center)
			[
				SNew( STextBlock )
				.Text(NSLOCTEXT("PropertyEditor", "MultipleValues", "Multiple Values"))
				.Font(NormalText)
				.ColorAndOpacity(FSlateColor(FLinearColor::Black)) // we know the background is always white, so can safely set this to black
				.Visibility(this, &FColorStructCustomization::GetMultipleValuesTextVisibility)
			]
		]
		+ SHorizontalBox::Slot()
		.VAlign(VAlign_Center)
		[
			// Displays the color without alpha
			SNew( SColorBlock )
			.Color( this, &FColorStructCustomization::OnGetColorForColorBlock )
			.ShowBackgroundForAlpha(false)
			.IgnoreAlpha(true)
			.OnMouseButtonDown( this, &FColorStructCustomization::OnMouseButtonDownColorBlock )
			.Size( FVector2D( 35.0f, 12.0f ) )
		]
	];
}
void FTextureLODGroupLayout::GenerateHeaderRowContent(FDetailWidgetRow& NodeRow)
{
	UEnum* TextureGroupEnum = FindObject<UEnum>(NULL, TEXT("/Script/Engine.TextureGroup"));
	const FString LODGroupName = TextureGroupEnum->GetMetaData(TEXT("DisplayName"), LodGroup->Group);

	NodeRow.NameContent()
		[
			SNew(STextBlock)
			.Text(FText::FromString(LODGroupName))
			.Font(IDetailLayoutBuilder::GetDetailFont())
		];
}
Ejemplo n.º 6
0
FDetailWidgetRow FDetailGroup::GetWidgetRow()
{
	if( HeaderCustomization.IsValid() && HeaderCustomization->HasPropertyNode() )
	{
		return HeaderCustomization->PropertyRow->GetWidgetRow();
	}
	else if ( HeaderCustomization.IsValid() && HeaderCustomization->HasCustomWidget() )
	{
		return *HeaderCustomization->WidgetDecl;
	}
	else
	{
		FDetailWidgetRow Row;

		Row.NameContent()
		[
			MakeNameWidget()
		];

		return Row;
	}
}
void FDetailPropertyRow::MakeValueWidget( FDetailWidgetRow& Row, const TSharedPtr<FDetailWidgetRow> InCustomRow, bool bAddWidgetDecoration ) const
{
	EVerticalAlignment VerticalAlignment = VAlign_Center;
	EHorizontalAlignment HorizontalAlignment = HAlign_Left;

	TOptional<float> MinWidth;
	TOptional<float> MaxWidth;

	if( InCustomRow.IsValid() )
	{
		VerticalAlignment = InCustomRow->ValueWidget.VerticalAlignment;
		HorizontalAlignment = InCustomRow->ValueWidget.HorizontalAlignment;
	}

	TAttribute<bool> IsEnabledAttrib = CustomIsEnabledAttrib;
	if( HasEditCondition() )
	{
		IsEnabledAttrib.Bind( this, &FDetailPropertyRow::GetEnabledState );
	}

	TSharedRef<SHorizontalBox> ValueWidget = 
		SNew( SHorizontalBox )
		.IsEnabled( IsEnabledAttrib );

	if( InCustomRow.IsValid() )
	{
		MinWidth = InCustomRow->ValueWidget.MinWidth;
		MaxWidth = InCustomRow->ValueWidget.MaxWidth;

		ValueWidget->AddSlot()
		[
			InCustomRow->ValueWidget.Widget
		];
	}
	else
	{
		TSharedPtr<SPropertyValueWidget> PropertyValue;

		ValueWidget->AddSlot()
		.Padding( 0.0f, 0.0f, 4.0f, 0.0f )
		[
			SAssignNew( PropertyValue, SPropertyValueWidget, PropertyEditor, GetPropertyUtilities() )
			.ShowPropertyButtons( false ) // We handle this ourselves
		];

		MinWidth = PropertyValue->GetMinDesiredWidth();
		MaxWidth = PropertyValue->GetMaxDesiredWidth();
	}

	if(bAddWidgetDecoration)
	{
		if( bShowPropertyButtons )
		{
			TArray< TSharedRef<SWidget> > RequiredButtons;
			PropertyEditorHelpers::MakeRequiredPropertyButtons( PropertyEditor.ToSharedRef(), /*OUT*/RequiredButtons );

			for( int32 ButtonIndex = 0; ButtonIndex < RequiredButtons.Num(); ++ButtonIndex )
			{
				ValueWidget->AddSlot()
				.AutoWidth()
				.HAlign(HAlign_Left)
				.VAlign(VAlign_Center)
				.Padding(2.0f, 1.0f)
				[ 
					RequiredButtons[ButtonIndex]
				];
			}
		}

		if (PropertyHandle->HasMetaData(TEXT("ConfigHierarchyEditable")))
		{
			ValueWidget->AddSlot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			.HAlign(HAlign_Left)
			.Padding(0.0f, 0.0f, 4.0f, 0.0f)
			[
				PropertyCustomizationHelpers::MakeEditConfigHierarchyButton(FSimpleDelegate::CreateSP(PropertyEditor.ToSharedRef(), &FPropertyEditor::EditConfigHierarchy))
			];
		}

		if (!PropertyHandle->HasMetaData(TEXT("NoResetToDefault")))
		{
			ValueWidget->AddSlot()
			.Padding( 2.0f, 0.0f )
			.AutoWidth()
			.VAlign(VAlign_Center)
			.HAlign(HAlign_Left)
			[
				SNew( SResetToDefaultPropertyEditor, PropertyEditor.ToSharedRef() )
				.IsEnabled( IsEnabledAttrib )
				.CustomResetToDefault(CustomResetToDefault)
			];
		}
	}

	Row.ValueContent()
	.HAlign( HorizontalAlignment )
	.VAlign( VerticalAlignment )	
	.MinDesiredWidth( MinWidth )
	.MaxDesiredWidth( MaxWidth )
	[
		ValueWidget
	];
}
void FDetailPropertyRow::MakeNameOrKeyWidget( FDetailWidgetRow& Row, const TSharedPtr<FDetailWidgetRow> InCustomRow ) const
{
	EVerticalAlignment VerticalAlignment = VAlign_Center;
	EHorizontalAlignment HorizontalAlignment = HAlign_Fill;

	bool bHasKeyNode = PropertyNode->GetPropertyKeyNode().IsValid();

	if( !bHasKeyNode && InCustomRow.IsValid() )
	{
		VerticalAlignment = InCustomRow->NameWidget.VerticalAlignment;
		HorizontalAlignment = InCustomRow->NameWidget.HorizontalAlignment;
	}

	TAttribute<bool> IsEnabledAttrib = CustomIsEnabledAttrib;

	TSharedRef<SHorizontalBox> NameHorizontalBox = SNew( SHorizontalBox );
	
	if( HasEditCondition() )
	{
		IsEnabledAttrib.Bind( this, &FDetailPropertyRow::GetEnabledState );

		NameHorizontalBox->AddSlot()
		.AutoWidth()
		.Padding( 0.0f, 0.0f )
		.VAlign(VAlign_Center)
		[
			SNew( SEditConditionWidget, PropertyEditor )
			.CustomEditCondition( CustomEditCondition.IsValid() ? *CustomEditCondition : FCustomEditCondition() )
		];
	}

	TSharedPtr<SWidget> NameWidget;

	// Key nodes will take precedence over custom rows.
	if (bHasKeyNode)
	{
		const TSharedRef<IPropertyUtilities> PropertyUtilities = ParentCategory.Pin()->GetParentLayoutImpl().GetPropertyUtilities();

		NameWidget =
			SNew(SPropertyValueWidget, PropertyKeyEditor, PropertyUtilities)
			.IsEnabled(IsEnabledAttrib)
			.ShowPropertyButtons(false);
	}
	else if(InCustomRow.IsValid())
	{
		NameWidget = 
			SNew( SBox )
			.IsEnabled( IsEnabledAttrib )
			[
				InCustomRow->NameWidget.Widget
			];
	}
	else
	{
		NameWidget = 
			SNew( SPropertyNameWidget, PropertyEditor )
			.IsEnabled( IsEnabledAttrib )
			.DisplayResetToDefault( false );
	}

	SHorizontalBox::FSlot& Slot = NameHorizontalBox->AddSlot()
	[
		NameWidget.ToSharedRef()
	];

	if (bHasKeyNode)
	{
		Slot.Padding(0.0f, 0.0f, 20.0f, 0.0f);
	}
	else
	{
		Slot.AutoWidth();
	}

	Row.NameContent()
	.HAlign( HorizontalAlignment )
	.VAlign( VerticalAlignment )
	[
		NameHorizontalBox
	];
}
void FIntervalStructCustomization<NumericType>::CustomizeHeader(TSharedRef<IPropertyHandle> StructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
	// Get handles to the properties we're interested in
	MinValueHandle = StructPropertyHandle->GetChildHandle(TEXT("Min"));
	MaxValueHandle = StructPropertyHandle->GetChildHandle(TEXT("Max"));
	check(MinValueHandle.IsValid());
	check(MaxValueHandle.IsValid());

	// Get min/max metadata values if defined
	auto Property = StructPropertyHandle->GetProperty();
	if (Property != nullptr)
	{
		if (Property->HasMetaData(TEXT("UIMin")))
		{
			MinAllowedValue = TOptional<NumericType>(IntervalMetadata::FGetHelper<NumericType>::GetMetaData(Property, TEXT("UIMin")));
		}

		if (Property->HasMetaData(TEXT("UIMax")))
		{
			MaxAllowedValue = TOptional<NumericType>(IntervalMetadata::FGetHelper<NumericType>::GetMetaData(Property, TEXT("UIMax")));
		}
	}

	// Make weak pointers to be passed as payloads to the widgets
	TWeakPtr<IPropertyHandle> MinValueWeakPtr = MinValueHandle;
	TWeakPtr<IPropertyHandle> MaxValueWeakPtr = MaxValueHandle;

	// Build the widgets
	HeaderRow.NameContent()
	[
		StructPropertyHandle->CreatePropertyNameWidget()
	]
	.ValueContent()
	.MinDesiredWidth(200.0f)
	//.MaxDesiredWidth(200.0f)
	[
		SNew(SBox)
		.Padding(FMargin(0.0f, 3.0f, 0.0f, 2.0f))
		[
			SNew(SHorizontalBox)

			+SHorizontalBox::Slot()
			.Padding(FMargin(0.0f, 0.0f, 5.0f, 0.0f))
			.VAlign(VAlign_Center)
			[
				SNew(SNumericEntryBox<NumericType>)
				.Value(this, &FIntervalStructCustomization<NumericType>::OnGetValue, MinValueWeakPtr)
				.MinValue(MinAllowedValue)
				.MinSliderValue(MinAllowedValue)
				.MaxValue(this, &FIntervalStructCustomization<NumericType>::OnGetValue, MaxValueWeakPtr)
				.MaxSliderValue(this, &FIntervalStructCustomization<NumericType>::OnGetValue, MaxValueWeakPtr)
				.OnValueCommitted(this, &FIntervalStructCustomization<NumericType>::OnValueCommitted, MinValueWeakPtr)
				.OnValueChanged(this, &FIntervalStructCustomization<NumericType>::OnValueChanged, MinValueWeakPtr)
				.OnBeginSliderMovement(this, &FIntervalStructCustomization<NumericType>::OnBeginSliderMovement)
				.OnEndSliderMovement(this, &FIntervalStructCustomization<NumericType>::OnEndSliderMovement)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.AllowSpin(true)
				.LabelVAlign(VAlign_Center)
				.Label()
				[
					SNew(STextBlock)
					.Font(IDetailLayoutBuilder::GetDetailFont())
					.Text(LOCTEXT("MinLabel", "Min"))
				]
			]

			+SHorizontalBox::Slot()
			.Padding(FMargin(0.0f, 0.0f, 5.0f, 0.0f))
			.VAlign(VAlign_Center)
			[
				SNew(SNumericEntryBox<NumericType>)
				.Value(this, &FIntervalStructCustomization<NumericType>::OnGetValue, MaxValueWeakPtr)
				.MinValue(this, &FIntervalStructCustomization<NumericType>::OnGetValue, MinValueWeakPtr)
				.MinSliderValue(this, &FIntervalStructCustomization<NumericType>::OnGetValue, MinValueWeakPtr)
				.MaxValue(MaxAllowedValue)
				.MaxSliderValue(MaxAllowedValue)
				.OnValueCommitted(this, &FIntervalStructCustomization<NumericType>::OnValueCommitted, MaxValueWeakPtr)
				.OnValueChanged(this, &FIntervalStructCustomization<NumericType>::OnValueChanged, MaxValueWeakPtr)
				.OnBeginSliderMovement(this, &FIntervalStructCustomization<NumericType>::OnBeginSliderMovement)
				.OnEndSliderMovement(this, &FIntervalStructCustomization<NumericType>::OnEndSliderMovement)
				.Font(IDetailLayoutBuilder::GetDetailFont())
				.AllowSpin(true)
				.LabelVAlign(VAlign_Center)
				.Label()
				[
					SNew(STextBlock)
					.Font(IDetailLayoutBuilder::GetDetailFont())
					.Text(LOCTEXT("MaxLabel", "Max"))
				]
			]
		]
	];
}