// Copyright Epic Games, Inc. All Rights Reserved. #include "EnumColumnEditor.h" #include "ChooserColumnHeader.h" #include "ChooserTableEditor.h" #include "DetailLayoutBuilder.h" #include "EnumColumn.h" #include "GraphEditorSettings.h" #include "ObjectChooserWidgetFactories.h" #include "OutputEnumColumn.h" #include "ScopedTransaction.h" #include "SPropertyAccessChainWidget.h" #include "Framework/MultiBox/MultiBoxBuilder.h" #include "Widgets/Input/SButton.h" #include "Widgets/Input/SComboButton.h" #define LOCTEXT_NAMESPACE "EnumColumnEditor" namespace UE::ChooserEditor { TSharedRef SEnumCell::GenerateEnumMenu() const { if (const UEnum* EnumSource = Enum.Get()) { FMenuBuilder MenuBuilder(true, nullptr); for (int32 EnumIndex = 0; EnumIndex < EnumSource->NumEnums() - 1; ++EnumIndex) { const bool bIsHidden = EnumSource->HasMetaData(TEXT("Hidden"), EnumIndex); if (!bIsHidden) { MenuBuilder.AddMenuEntry(EnumSource->GetDisplayNameTextByIndex(EnumIndex), FText()/*todo tooltip*/, FSlateIcon(), FUIAction( FExecuteAction::CreateLambda([this, MenuEntryEnumValue = EnumSource->GetValueByIndex(EnumIndex)]() { OnValueSet.ExecuteIfBound(MenuEntryEnumValue); }) )); } } return MenuBuilder.MakeWidget(); } return SNullWidget::NullWidget; } TSharedRef SEnumCell::CreateEnumComboBox() { return SNew(SComboButton) .IsEnabled_Lambda([this](){ return IsEnabled(); } ) .OnGetMenuContent(this, &SEnumCell::GenerateEnumMenu) .VAlign(VAlign_Center) .ButtonContent() [ SNew(STextBlock) .Font(IDetailLayoutBuilder::GetDetailFont()) .Text_Lambda([this]() { if (const UEnum* EnumSource = Enum.Get()) { return EnumSource->GetDisplayNameTextByValue(EnumValue.Get()); } return FText(); }) ]; } void SEnumCell::Construct( const FArguments& InArgs) { SetEnabled(InArgs._IsEnabled); Enum = InArgs._Enum; EnumValue = InArgs._EnumValue; OnValueSet = InArgs._OnValueSet; ChildSlot [ CreateEnumComboBox() ]; } TSharedRef CreateEnumColumnWidget(UChooserTable* Chooser, FChooserColumnBase* Column, int Row) { FEnumColumn* EnumColumn = 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("Enum Value Tooltip", "Enum Value: cells pass if the cell value is equal to the column input value"); const FText ColumnName = LOCTEXT("Enum Value","Enum Value"); TSharedPtr DebugWidget = nullptr; if (Chooser->GetEnableDebugTesting()) { DebugWidget = SNew(SEnumCell) .Enum_Lambda([EnumColumn]() { return EnumColumn->GetEnum(); }) .OnValueSet_Lambda([EnumColumn](int Value) { EnumColumn->TestValue = Value; }) .EnumValue_Lambda([EnumColumn]() { return EnumColumn->TestValue; }) .IsEnabled_Lambda([Chooser] { return !Chooser->HasDebugTarget(); }); } return MakeColumnHeaderWidget(Chooser, Column, ColumnName, ColumnTooltip, ColumnIcon, DebugWidget, FChooserWidgetValueChanged::CreateLambda([EnumColumn]() { EnumColumn->EnumChanged(EnumColumn->InputValue.Get().GetEnum()); })); } // create cell widget return SNew(SHorizontalBox) + SHorizontalBox::Slot().AutoWidth() [ SNew(SBox).WidthOverride(Row < 0 ? 0 : 55) [ SNew(SButton).ButtonStyle(FAppStyle::Get(),"FlatButton").TextStyle(FAppStyle::Get(),"RichTextBlock.Bold").HAlign(HAlign_Center) .Visibility(Row < 0 ? EVisibility::Hidden : EVisibility::Visible) .Text_Lambda([EnumColumn, Row]() { switch (EnumColumn->RowValues[Row].Comparison) { case EEnumColumnCellValueComparison::MatchEqual: return LOCTEXT("CompEqual", "="); case EEnumColumnCellValueComparison::MatchNotEqual: return LOCTEXT("CompNotEqual", "Not"); case EEnumColumnCellValueComparison::MatchAny: return LOCTEXT("CompAny", "Any"); } return FText::GetEmpty(); }) .OnClicked_Lambda([EnumColumn, Chooser, Row]() { if (EnumColumn->RowValues.IsValidIndex(Row)) { const FScopedTransaction Transaction(LOCTEXT("Edit Comparison", "Edit Comparison Operation")); Chooser->Modify(true); // cycle through comparison options EEnumColumnCellValueComparison& Comparison = EnumColumn->RowValues[Row].Comparison; const int32 NextComparison = (static_cast(Comparison) + 1) % static_cast(EEnumColumnCellValueComparison::Modulus); Comparison = static_cast(NextComparison); } return FReply::Handled(); }) ] ] + SHorizontalBox::Slot().FillWidth(1) [ SNew(SEnumCell) .Enum_Lambda([EnumColumn]() { return EnumColumn->GetEnum(); }) .OnValueSet_Lambda([Chooser, EnumColumn, Row](int Value) { FScopedTransaction Transaction(LOCTEXT("Set Enum Value", "Set Enum Value")); Chooser->Modify(); if (EnumColumn->RowValues.IsValidIndex(Row)) { EnumColumn->RowValues[Row].Value = static_cast(Value); if (EnumColumn->InputValue.IsValid()) { if (const UEnum* Enum = EnumColumn->InputValue.Get().GetEnum()) { EnumColumn->RowValues[Row].ValueName = Enum->GetNameByValue(Value); } } } }) .EnumValue_Lambda([EnumColumn, Row]() { return EnumColumn->RowValues.IsValidIndex(Row) ? static_cast(EnumColumn->RowValues[Row].Value) : 0; }) .Visibility_Lambda([EnumColumn,Column, Row]() { return (EnumColumn->RowValues.IsValidIndex(Row) && EnumColumn->RowValues[Row].Comparison == EEnumColumnCellValueComparison::MatchAny) ? EVisibility::Collapsed : EVisibility::Visible; }) ]; } TSharedRef CreateOutputEnumColumnWidget(UChooserTable* Chooser, FChooserColumnBase* Column, int Row) { FOutputEnumColumn* EnumColumn = static_cast(Column); if (Row == ColumnWidget_SpecialIndex_Header) { const FSlateBrush* ColumnIcon = FCoreStyle::Get().GetBrush("Icons.ArrowRight"); const FText ColumnTooltip = LOCTEXT("Output Enum Tooltip", "Output Enum: writes the value from cell in the result row to the bound variable"); const FText ColumnName = LOCTEXT("Output Enum","Output Enum"); TSharedPtr DebugWidget = nullptr; if (Chooser->GetEnableDebugTesting()) { DebugWidget = SNew(SEnumCell) .IsEnabled(false) .Enum_Lambda([EnumColumn](){ return EnumColumn->GetEnum(); } ) .EnumValue_Lambda([EnumColumn]() { return static_cast(EnumColumn->TestValue); }); } return MakeColumnHeaderWidget(Chooser, Column, ColumnName, ColumnTooltip, ColumnIcon, DebugWidget, FChooserWidgetValueChanged::CreateLambda([EnumColumn]() { EnumColumn->EnumChanged(EnumColumn->InputValue.Get().GetEnum()); })); } else if (Row == ColumnWidget_SpecialIndex_Fallback) { return SNew(SEnumCell) .Enum_Lambda([EnumColumn](){ return EnumColumn->GetEnum(); } ) .OnValueSet_Lambda([Chooser, EnumColumn](int Value) { FScopedTransaction Transaction(LOCTEXT("Set Enum Value", "Set Enum Value")); Chooser->Modify(); EnumColumn->FallbackValue.Value = Value; if (EnumColumn->InputValue.IsValid()) { if (const UEnum* Enum = EnumColumn->InputValue.Get().GetEnum()) { EnumColumn->FallbackValue.ValueName = Enum->GetNameByValue(Value); } } }) .EnumValue_Lambda([EnumColumn]() { return EnumColumn->FallbackValue.Value; }); } // create cell widget return SNew(SEnumCell) .Enum_Lambda([EnumColumn](){ return EnumColumn->GetEnum(); } ) .OnValueSet_Lambda([EnumColumn, Chooser, Row](int Value) { FScopedTransaction Transaction(LOCTEXT("Set Enum Value", "Set Enum Value")); Chooser->Modify(); if (EnumColumn->RowValues.IsValidIndex(Row)) { EnumColumn->RowValues[Row].Value = static_cast(Value); if (EnumColumn->InputValue.IsValid()) { if (const UEnum* Enum = EnumColumn->InputValue.Get().GetEnum()) { EnumColumn->RowValues[Row].ValueName = Enum->GetNameByValue(Value); } } } }) .EnumValue_Lambda([EnumColumn, Row]() { return EnumColumn->RowValues.IsValidIndex(Row) ? static_cast(EnumColumn->RowValues[Row].Value) : 0; }); } TSharedRef CreateEnumPropertyWidget(bool bReadOnly, UObject* TransactionObject, void* Value, UClass* ResultBaseClass, FChooserWidgetValueChanged ValueChanged) { IHasContextClass* HasContextClass = Cast(TransactionObject); FEnumContextProperty* ContextProperty = reinterpret_cast(Value); return SNew(SPropertyAccessChainWidget).ContextClassOwner(HasContextClass).AllowFunctions(false).BindingColor("BytePinTypeColor").TypeFilter("enum") .PropertyBindingValue(&ContextProperty->Binding) .OnValueChanged(ValueChanged); } void RegisterEnumWidgets() { FObjectChooserWidgetFactories::RegisterWidgetCreator(FEnumContextProperty::StaticStruct(), CreateEnumPropertyWidget); FObjectChooserWidgetFactories::RegisterColumnWidgetCreator(FEnumColumn::StaticStruct(), CreateEnumColumnWidget); FObjectChooserWidgetFactories::RegisterColumnWidgetCreator(FOutputEnumColumn::StaticStruct(), CreateOutputEnumColumnWidget); } } #undef LOCTEXT_NAMESPACE