572 lines
20 KiB
C++
572 lines
20 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "RawDistributionVectorStructCustomization.h"
|
|
|
|
#include "Delegates/Delegate.h"
|
|
#include "DetailLayoutBuilder.h"
|
|
#include "DetailWidgetRow.h"
|
|
#include "Editor.h"
|
|
#include "Editor/EditorEngine.h"
|
|
#include "Engine/Engine.h"
|
|
#include "Fonts/SlateFontInfo.h"
|
|
#include "Framework/SlateDelegates.h"
|
|
#include "HAL/PlatformCrt.h"
|
|
#include "IDetailChildrenBuilder.h"
|
|
#include "IDetailCustomNodeBuilder.h"
|
|
#include "Input/Events.h"
|
|
#include "Input/Reply.h"
|
|
#include "InputCoreTypes.h"
|
|
#include "Internationalization/Internationalization.h"
|
|
#include "Internationalization/Text.h"
|
|
#include "Math/Color.h"
|
|
#include "Math/UnrealMathSSE.h"
|
|
#include "Math/Vector.h"
|
|
#include "Math/Vector2D.h"
|
|
#include "Misc/AssertionMacros.h"
|
|
#include "Misc/Attribute.h"
|
|
#include "Misc/Optional.h"
|
|
#include "PropertyCustomizationHelpers.h"
|
|
#include "PropertyEditorModule.h"
|
|
#include "PropertyHandle.h"
|
|
#include "Types/SlateEnums.h"
|
|
#include "UObject/Class.h"
|
|
#include "UObject/Field.h"
|
|
#include "UObject/NameTypes.h"
|
|
#include "UObject/UnrealNames.h"
|
|
#include "UObject/UnrealType.h"
|
|
#include "Widgets/Colors/SColorBlock.h"
|
|
#include "Widgets/Colors/SColorPicker.h"
|
|
#include "Widgets/DeclarativeSyntaxSupport.h"
|
|
#include "Widgets/Input/SNumericEntryBox.h"
|
|
#include "Widgets/Layout/SBox.h"
|
|
#include "Widgets/Text/STextBlock.h"
|
|
|
|
class SWidget;
|
|
struct FGeometry;
|
|
|
|
#define LOCTEXT_NAMESPACE "RawDistributionVectorStructCustomization"
|
|
|
|
|
|
class FReplaceVectorWithLinearColorBuilder : public IDetailCustomNodeBuilder, public TSharedFromThis<FReplaceVectorWithLinearColorBuilder>
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param The property handle representing this item
|
|
*/
|
|
explicit FReplaceVectorWithLinearColorBuilder(TSharedRef<IPropertyHandle> InPropertyHandle);
|
|
|
|
/**
|
|
* Sets a delegate that should be used when the custom node needs to rebuild children
|
|
*
|
|
* @param A delegate to invoke when the tree should rebuild this nodes children
|
|
*/
|
|
virtual void SetOnRebuildChildren(FSimpleDelegate InOnRegenerateChildren) override {}
|
|
|
|
|
|
/**
|
|
* Called to generate content in the header of this node ( the actual node content ).
|
|
* Only called if HasHeaderRow is true
|
|
*
|
|
* @param NodeRow The row to put content in
|
|
*/
|
|
virtual void GenerateHeaderRowContent(FDetailWidgetRow& NodeRow) override;
|
|
|
|
/**
|
|
* Called to generate child content of this node
|
|
*
|
|
* @param OutChildRows An array of rows to add children to
|
|
*/
|
|
virtual void GenerateChildContent(IDetailChildrenBuilder& ChildrenBuilder) override;
|
|
|
|
/**
|
|
* Called each tick if ReqiresTick is true
|
|
*/
|
|
virtual void Tick(float DeltaTime) override {}
|
|
|
|
/**
|
|
* @return true if this node requires tick, false otherwise
|
|
*/
|
|
virtual bool RequiresTick() const override { return false; }
|
|
|
|
/**
|
|
* @return true if this node should be collapsed in the tree
|
|
*/
|
|
virtual bool InitiallyCollapsed() const override { return false; }
|
|
|
|
/**
|
|
* @return The name of this custom builder. This is used as an identifier to save expansion state if needed
|
|
*/
|
|
virtual FName GetName() const override;
|
|
|
|
|
|
protected:
|
|
|
|
/**
|
|
* Creates a widget representing the FVector being pointed to as a FLinearColor
|
|
*/
|
|
TSharedRef<SWidget> CreateColorWidget(const TSharedPtr<IPropertyHandle>& StructHandle);
|
|
|
|
/**
|
|
* Adds a child widget representing a component of an FLinearColor
|
|
*
|
|
* @param StructHandle Handle of the FVector being represented as a FLinearColor
|
|
* @param Text Label text
|
|
* @param ElementIndex Element of the FVector it represents (0-2)
|
|
* @param ChildrenBuilder The builder object
|
|
*/
|
|
void AddColorChildProperty(const TSharedPtr<IPropertyHandle>& StructHandle, const FText& Text, int32 ElementIndex, IDetailChildrenBuilder& ChildrenBuilder);
|
|
|
|
/**
|
|
* Generates a child property, handling nested arrays and structs by creating a child property builder.
|
|
*
|
|
* @param Handle Property handle of the property being generated
|
|
* @param ChildrenBuilder The current builder object
|
|
*/
|
|
void GeneratePropertyContent(const TSharedRef<IPropertyHandle>& Handle, IDetailChildrenBuilder& ChildrenBuilder);
|
|
|
|
/**
|
|
* Called by the array builder when it needs to generate a new child widget
|
|
*
|
|
* @param ElementProperty Property handle of the array element
|
|
* @param ElementIndex Index of the element in the array
|
|
* @param ChildrenBuilder The current builder object
|
|
*/
|
|
void OnGenerateArrayElementWidget(TSharedRef<IPropertyHandle> ElementProperty, int32 ElementIndex, IDetailChildrenBuilder& ChildrenBuilder);
|
|
|
|
/**
|
|
* Called by the color element widgets to determine the current color element value
|
|
*
|
|
* @param StructHandle Property handle of the FVector representing the color
|
|
* @param ElementIndex Element of the FVector it represents (0-2)
|
|
*/
|
|
TOptional<float> OnGetColorElementValue(TSharedPtr<IPropertyHandle> StructHandle, int32 ElementIndex) const;
|
|
|
|
/**
|
|
* Called when a numeric component is set.
|
|
*
|
|
* @param NewValue New element value
|
|
* @param CommitType Specifies how the result was entered
|
|
* @param StructHandle Property handle of the FVector representing the color
|
|
* @param ElementIndex Element of the FVector it represents (0-2)
|
|
*/
|
|
void OnColorElementValueCommitted(float NewValue, ETextCommit::Type CommitType, TSharedPtr<IPropertyHandle> StructHandle, int32 ElementIndex);
|
|
|
|
/**
|
|
* Called when a numeric component is changed.
|
|
*
|
|
* @param NewValue New element value
|
|
* @param StructHandle Property handle of the FVector representing the color
|
|
* @param ElementIndex Element of the FVector it represents (0-2)
|
|
*/
|
|
void OnColorElementValueChanged(float NewValue, TSharedPtr<IPropertyHandle> StructHandle, int32 ElementIndex);
|
|
|
|
/** Called when the slider is moved on a numeric entry box */
|
|
void OnBeginSliderMovement();
|
|
|
|
/** Called when the slider is released on a numeric entry box */
|
|
void OnEndSliderMovement(float NewValue);
|
|
|
|
/** Returns the FLinearColor represented by the FVector pointed to by the property handle */
|
|
FLinearColor OnGetColorForColorBlock(TSharedPtr<IPropertyHandle> StructHandle) const;
|
|
|
|
/**
|
|
* Called when mouse is clicked on the color widget
|
|
*/
|
|
FReply OnMouseButtonDownColorBlock(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent, TSharedPtr<IPropertyHandle> StructHandle);
|
|
|
|
/** Creates a color picker window */
|
|
void CreateColorPicker(const TSharedPtr<IPropertyHandle>& StructHandle);
|
|
|
|
/**
|
|
* Called when a color is chosen from the color picker
|
|
*
|
|
* @param NewColor Color that was chosen
|
|
* @param StructHandle Property handle of the FVector representing the color
|
|
*/
|
|
void OnSetColorFromColorPicker(FLinearColor NewColor, TSharedPtr<IPropertyHandle> StructHandle);
|
|
|
|
/**
|
|
* Called when the color picker is cancelled
|
|
*
|
|
* @param OriginalColor Original value of the property
|
|
* @param StructHandle Property handle of the FVector representing the color
|
|
*/
|
|
void OnColorPickerCancelled(FLinearColor OriginalColor, TSharedPtr<IPropertyHandle> StructHandle);
|
|
|
|
/** Called when a drag starts in the color picker */
|
|
void OnColorPickerInteractiveBegin();
|
|
|
|
/** Called when a drag ends in the color picker */
|
|
void OnColorPickerInteractiveEnd();
|
|
|
|
private:
|
|
|
|
/** Holds the property handle being referenced by this builder object */
|
|
TSharedRef<IPropertyHandle> PropertyHandle;
|
|
|
|
/** true if the property is an FVector, and hence needs customization */
|
|
bool bIsVectorProperty;
|
|
|
|
/** true if the slider is being dragged in a numeric entry box */
|
|
bool bIsUsingSlider;
|
|
|
|
/** Original value of the property, prior to using the color picker */
|
|
FLinearColor OldColorValue;
|
|
|
|
/** Widget the Color Picker is parented to */
|
|
TSharedPtr<SWidget> ColorPickerParentWidget;
|
|
};
|
|
|
|
|
|
// Some helper functions for obtaining values from the FVector property, and converting them to FLinearColor
|
|
namespace
|
|
{
|
|
float GetColorElementValue(const TSharedPtr<IPropertyHandle>& StructHandle, int32 ElementIndex)
|
|
{
|
|
FVector Result;
|
|
ensure(StructHandle->GetValue(Result) == FPropertyAccess::Success);
|
|
return static_cast<float>(Result[ElementIndex]);
|
|
}
|
|
|
|
void SetColorElementValue(const TSharedPtr<IPropertyHandle>& StructHandle, int32 ElementIndex, float Value)
|
|
{
|
|
FVector Result;
|
|
ensure(StructHandle->GetValue(Result) == FPropertyAccess::Success);
|
|
Result[ElementIndex] = Value;
|
|
ensure(StructHandle->SetValue(Result) == FPropertyAccess::Success);
|
|
}
|
|
|
|
FLinearColor GetColorValue(const TSharedPtr<IPropertyHandle>& StructHandle)
|
|
{
|
|
FVector Result;
|
|
ensure(StructHandle->GetValue(Result) == FPropertyAccess::Success);
|
|
return FLinearColor(static_cast<float>(Result.X), static_cast<float>(Result.Y), static_cast<float>(Result.Z), 1.0f);
|
|
}
|
|
|
|
void SetColorValue(const TSharedPtr<IPropertyHandle>& StructHandle, FLinearColor Value)
|
|
{
|
|
FVector ValueAsVector(Value.R, Value.G, Value.B);
|
|
ensure(StructHandle->SetValue(ValueAsVector) == FPropertyAccess::Success);
|
|
}
|
|
}
|
|
|
|
|
|
FReplaceVectorWithLinearColorBuilder::FReplaceVectorWithLinearColorBuilder(TSharedRef<IPropertyHandle> InPropertyHandle)
|
|
: PropertyHandle(InPropertyHandle)
|
|
, bIsVectorProperty(false)
|
|
, bIsUsingSlider(false)
|
|
{
|
|
// Determine if this is an FVector - if so it will be specialized
|
|
FProperty* Property = InPropertyHandle->GetProperty();
|
|
|
|
if (FStructProperty* StructProperty = CastField<FStructProperty>(Property))
|
|
{
|
|
FName StructType = StructProperty->Struct->GetFName();
|
|
bIsVectorProperty = (StructType == NAME_Vector);
|
|
}
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::GenerateHeaderRowContent(FDetailWidgetRow& NodeRow)
|
|
{
|
|
// Only generate a header row if the handle has a valid FProperty.
|
|
// 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 FReplaceVectorWithLinearColorBuilder::GenerateChildContent(IDetailChildrenBuilder& ChildrenBuilder)
|
|
{
|
|
if (bIsVectorProperty)
|
|
{
|
|
// Customization - children of an FVector are made to look like color components of an FLinearColor
|
|
AddColorChildProperty(PropertyHandle, LOCTEXT("RedComponent", "R"), 0, ChildrenBuilder);
|
|
AddColorChildProperty(PropertyHandle, LOCTEXT("GreenComponent", "G"), 1, ChildrenBuilder);
|
|
AddColorChildProperty(PropertyHandle, LOCTEXT("BlueComponent", "B"), 2, ChildrenBuilder);
|
|
}
|
|
else
|
|
{
|
|
// Otherwise, go through the child properties and render them as normal
|
|
uint32 NumChildren;
|
|
ensure(PropertyHandle->GetNumChildren(NumChildren) == FPropertyAccess::Success);
|
|
|
|
for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ChildIndex++)
|
|
{
|
|
TSharedPtr<IPropertyHandle> ChildHandle = PropertyHandle->GetChildHandle(ChildIndex);
|
|
check(ChildHandle.IsValid());
|
|
GeneratePropertyContent(ChildHandle.ToSharedRef(), ChildrenBuilder);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
FName FReplaceVectorWithLinearColorBuilder::GetName() const
|
|
{
|
|
if (PropertyHandle->GetProperty() != nullptr)
|
|
{
|
|
return PropertyHandle->GetProperty()->GetFName();
|
|
}
|
|
|
|
return NAME_None;
|
|
}
|
|
|
|
|
|
|
|
TSharedRef<SWidget> FReplaceVectorWithLinearColorBuilder::CreateColorWidget(const TSharedPtr<IPropertyHandle>& StructHandle)
|
|
{
|
|
FSlateFontInfo NormalText = IDetailLayoutBuilder::GetDetailFont();
|
|
|
|
return SNew(SBox)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SAssignNew(ColorPickerParentWidget, SColorBlock)
|
|
.Color(this, &FReplaceVectorWithLinearColorBuilder::OnGetColorForColorBlock, StructHandle)
|
|
.ShowBackgroundForAlpha(false)
|
|
.AlphaDisplayMode(EColorBlockAlphaDisplayMode::Ignore)
|
|
.OnMouseButtonDown(this, &FReplaceVectorWithLinearColorBuilder::OnMouseButtonDownColorBlock, StructHandle)
|
|
.Size(FVector2D(70.0f, 12.0f))
|
|
];
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::AddColorChildProperty(const TSharedPtr<IPropertyHandle>& StructHandle, const FText& Text, int32 ElementIndex, IDetailChildrenBuilder& ChildrenBuilder)
|
|
{
|
|
ChildrenBuilder.AddCustomRow(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 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.AddCustomBuilder(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.AddCustomBuilder(StructBuilder);
|
|
}
|
|
else
|
|
{
|
|
// No children - just add the property.
|
|
ChildrenBuilder.AddProperty(Handle);
|
|
}
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::OnGenerateArrayElementWidget(TSharedRef<IPropertyHandle> ElementProperty, int32 ElementIndex, IDetailChildrenBuilder& ChildrenBuilder)
|
|
{
|
|
GeneratePropertyContent(ElementProperty, ChildrenBuilder);
|
|
}
|
|
|
|
|
|
TOptional<float> FReplaceVectorWithLinearColorBuilder::OnGetColorElementValue(TSharedPtr<IPropertyHandle> StructHandle, int32 ElementIndex) const
|
|
{
|
|
return GetColorElementValue(StructHandle, ElementIndex);
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::OnColorElementValueCommitted(float NewValue, ETextCommit::Type CommitType, TSharedPtr<IPropertyHandle> StructHandle, int32 ElementIndex)
|
|
{
|
|
SetColorElementValue(StructHandle, ElementIndex, NewValue);
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::OnColorElementValueChanged(float NewValue, TSharedPtr<IPropertyHandle> StructHandle, int32 ElementIndex)
|
|
{
|
|
if (bIsUsingSlider)
|
|
{
|
|
SetColorElementValue(StructHandle, ElementIndex, NewValue);
|
|
}
|
|
}
|
|
|
|
|
|
FLinearColor FReplaceVectorWithLinearColorBuilder::OnGetColorForColorBlock(TSharedPtr<IPropertyHandle> StructHandle) const
|
|
{
|
|
return GetColorValue(StructHandle);
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::OnBeginSliderMovement()
|
|
{
|
|
GEditor->BeginTransaction(LOCTEXT("SetColorProperty", "Set Color Property"));
|
|
bIsUsingSlider = true;
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::OnEndSliderMovement(float NewValue)
|
|
{
|
|
bIsUsingSlider = false;
|
|
GEditor->EndTransaction();
|
|
}
|
|
|
|
|
|
FReply FReplaceVectorWithLinearColorBuilder::OnMouseButtonDownColorBlock(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent, TSharedPtr<IPropertyHandle> StructHandle)
|
|
{
|
|
if (MouseEvent.GetEffectingButton() != EKeys::LeftMouseButton)
|
|
{
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
CreateColorPicker(StructHandle);
|
|
return FReply::Handled();
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::CreateColorPicker(const TSharedPtr<IPropertyHandle>& StructHandle)
|
|
{
|
|
OldColorValue = GetColorValue(StructHandle);
|
|
|
|
FColorPickerArgs PickerArgs;
|
|
PickerArgs.bUseAlpha = false;
|
|
PickerArgs.bOnlyRefreshOnMouseUp = false;
|
|
PickerArgs.bOnlyRefreshOnOk = false;
|
|
PickerArgs.DisplayGamma = TAttribute<float>::Create(TAttribute<float>::FGetter::CreateUObject(GEngine, &UEngine::GetDisplayGamma));
|
|
PickerArgs.OnColorCommitted = FOnLinearColorValueChanged::CreateSP(this, &FReplaceVectorWithLinearColorBuilder::OnSetColorFromColorPicker, StructHandle);
|
|
PickerArgs.OnColorPickerCancelled = FOnColorPickerCancelled::CreateSP(this, &FReplaceVectorWithLinearColorBuilder::OnColorPickerCancelled, StructHandle);
|
|
PickerArgs.OnInteractivePickBegin = FSimpleDelegate::CreateSP(this, &FReplaceVectorWithLinearColorBuilder::OnColorPickerInteractiveBegin);
|
|
PickerArgs.OnInteractivePickEnd = FSimpleDelegate::CreateSP(this, &FReplaceVectorWithLinearColorBuilder::OnColorPickerInteractiveEnd);
|
|
PickerArgs.InitialColor = OldColorValue;
|
|
PickerArgs.ParentWidget = ColorPickerParentWidget;
|
|
|
|
OpenColorPicker(PickerArgs);
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::OnSetColorFromColorPicker(FLinearColor NewColor, TSharedPtr<IPropertyHandle> StructHandle)
|
|
{
|
|
SetColorValue(StructHandle, NewColor);
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::OnColorPickerCancelled(FLinearColor OriginalColor, TSharedPtr<IPropertyHandle> StructHandle)
|
|
{
|
|
SetColorValue(StructHandle, OldColorValue);
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::OnColorPickerInteractiveBegin()
|
|
{
|
|
GEditor->BeginTransaction(LOCTEXT("SetColorProperty", "Set Color Property"));
|
|
}
|
|
|
|
|
|
void FReplaceVectorWithLinearColorBuilder::OnColorPickerInteractiveEnd()
|
|
{
|
|
GEditor->EndTransaction();
|
|
}
|
|
|
|
|
|
TSharedRef<IPropertyTypeCustomization> FRawDistributionVectorStructCustomization::MakeInstance()
|
|
{
|
|
return MakeShareable(new FRawDistributionVectorStructCustomization);
|
|
}
|
|
|
|
|
|
void FRawDistributionVectorStructCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> StructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
|
|
{
|
|
HeaderRow
|
|
.NameContent()
|
|
[
|
|
StructPropertyHandle->CreatePropertyNameWidget()
|
|
]
|
|
.ValueContent()
|
|
.MinDesiredWidth(1)
|
|
.MaxDesiredWidth(4096)
|
|
[
|
|
StructPropertyHandle->CreatePropertyValueWidget()
|
|
];
|
|
}
|
|
|
|
|
|
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.AddCustomBuilder(CustomBuilder);
|
|
}
|
|
else
|
|
{
|
|
StructBuilder.AddProperty(ChildHandle.ToSharedRef());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|