// Copyright Epic Games, Inc. All Rights Reserved. #include "MultiEnumColumnEditor.h" #include "EnumColumnEditor.h" #include "MultiEnumColumn.h" #include "SPropertyAccessChainWidget.h" #include "ObjectChooserWidgetFactories.h" #include "ChooserColumnHeader.h" #include "ChooserTableEditor.h" #include "GraphEditorSettings.h" #include "SEnumCombo.h" #include "TransactionCommon.h" #include "Widgets/Input/SButton.h" #include "ScopedTransaction.h" #define LOCTEXT_NAMESPACE "MultiEnumColumnEditor" namespace UE::ChooserEditor { // Wrapper widget for EnumComboBox which will reconstruct the combo box when the Enum has changed template class SMultiEnumCell : public SCompoundWidget { public: DECLARE_DELEGATE_OneParam(FOnValueSet, int); SLATE_BEGIN_ARGS(SMultiEnumCell) {} SLATE_ARGUMENT(UObject*, TransactionObject) SLATE_ARGUMENT(ColumnType*, MultiEnumColumn) SLATE_ATTRIBUTE(int32, EnumValue); SLATE_EVENT(FOnValueSet, OnValueSet) SLATE_END_ARGS() TSharedRef CreateEnumComboBox() { if (const ColumnType* MultiEnumColumnPointer = MultiEnumColumn) { if (MultiEnumColumnPointer->InputValue.IsValid()) { if (const UEnum* Enum = MultiEnumColumnPointer->InputValue.template Get().GetEnum()) { return SNew(SEnumComboBox, Enum) .bForceBitFlags(true) .OverrideNoFlagsSetText(LOCTEXT("(Any)", "(Any)")) .IsEnabled_Lambda([this](){ return IsEnabled(); } ) .CurrentValue(EnumValue) .OnEnumSelectionChanged_Lambda([this](int32 InEnumValue, ESelectInfo::Type) { const FScopedTransaction Transaction(LOCTEXT("Edit RHS", "Edit Enum Value")); TransactionObject->Modify(true); OnValueSet.ExecuteIfBound(InEnumValue); }); } } } return SNullWidget::NullWidget; } void UpdateEnumComboBox() { ChildSlot[ CreateEnumComboBox() ]; } virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override { const UEnum* CurrentEnumSource = nullptr; if (MultiEnumColumn->InputValue.IsValid()) { CurrentEnumSource = MultiEnumColumn->InputValue.template Get().GetEnum(); } if (EnumSource != CurrentEnumSource) { EnumComboBorder->SetContent(CreateEnumComboBox()); EnumSource = CurrentEnumSource; } } void Construct( const FArguments& InArgs) { SetEnabled(InArgs._IsEnabled); SetCanTick(true); MultiEnumColumn = InArgs._MultiEnumColumn; TransactionObject = InArgs._TransactionObject; EnumValue = InArgs._EnumValue; OnValueSet = InArgs._OnValueSet; if (MultiEnumColumn) { if (MultiEnumColumn->InputValue.IsValid()) { EnumSource = MultiEnumColumn->InputValue.template Get().GetEnum(); } } UpdateEnumComboBox(); int Row = RowIndex.Get(); ChildSlot [ SAssignNew(EnumComboBorder, SBorder).Padding(0).BorderBackgroundColor(FLinearColor(0,0,0,0)) [ CreateEnumComboBox() ] ]; } ~SMultiEnumCell() { } private: UObject* TransactionObject = nullptr; ColumnType* MultiEnumColumn = nullptr; const UEnum* EnumSource = nullptr; TSharedPtr EnumComboBorder; TAttribute RowIndex; FDelegateHandle EnumChangedHandle; FOnValueSet OnValueSet; TAttribute EnumValue; }; TSharedRef CreateMultiEnumColumnWidget(UChooserTable* Chooser, FChooserColumnBase* Column, int Row) { FMultiEnumColumn* MultiEnumColumn = static_cast(Column); if (Row == ColumnWidget_SpecialIndex_Fallback) { return SNullWidget::NullWidget; } if (Row == ColumnWidget_SpecialIndex_Header) { const FSlateBrush* ColumnIcon = FCoreStyle::Get().GetBrush("Icons.Filter"); const FText ColumnTooltip = LOCTEXT("Multi Enum Tooltip", "Enum Any: cells will pass if the input value is any of the enum values checked in the cell"); const FText ColumnName = LOCTEXT("Enum Or","Enum (Or)"); TSharedPtr DebugWidget = nullptr; if (Chooser->GetEnableDebugTesting()) { DebugWidget = SNew(SEnumCell) .Enum_Lambda([MultiEnumColumn] () { return MultiEnumColumn->GetEnum(); }) .OnValueSet_Lambda([MultiEnumColumn](int Value) { MultiEnumColumn->TestValue = Value; }) .EnumValue_Lambda([MultiEnumColumn]() { return MultiEnumColumn->TestValue; }) .IsEnabled_Lambda([Chooser] { return !Chooser->HasDebugTarget(); }); // need to fix support for bitfield enums: // DebugWidget = SNew(SMultiEnumCell).TransactionObject(Chooser).MultiEnumColumn(MultiEnumColumn) // .OnValueSet_Lambda([MultiEnumColumn](int Value) { MultiEnumColumn->TestValue = Value; }) // .EnumValue_Lambda([MultiEnumColumn]() { return MultiEnumColumn->TestValue; }) // .IsEnabled_Lambda([Chooser] { return !Chooser->HasDebugTarget(); }); } return MakeColumnHeaderWidget(Chooser, Column, ColumnName, ColumnTooltip, ColumnIcon, DebugWidget); } // create cell widget return SNew(SMultiEnumCell).TransactionObject(Chooser).MultiEnumColumn(MultiEnumColumn) .OnValueSet_Lambda([MultiEnumColumn, Row](int Value) { if (MultiEnumColumn->RowValues.IsValidIndex(Row)) { MultiEnumColumn->RowValues[Row].Value = static_cast(Value); } }) .EnumValue_Lambda([MultiEnumColumn, Row]() { return MultiEnumColumn->RowValues.IsValidIndex(Row) ? static_cast(MultiEnumColumn->RowValues[Row].Value) : 0; }); } void RegisterMultiEnumWidgets() { FObjectChooserWidgetFactories::RegisterColumnWidgetCreator(FMultiEnumColumn::StaticStruct(), CreateMultiEnumColumnWidget); } } #undef LOCTEXT_NAMESPACE