// Copyright Epic Games, Inc. All Rights Reserved. #include "SInterchangeAssetCard.h" #include "GameFramework/Actor.h" #include "InterchangeEditorPipelineStyle.h" #include "InterchangePipelineBase.h" #include "Nodes/InterchangeBaseNodeContainer.h" #include "Nodes/InterchangeFactoryBaseNode.h" #include "SSimpleButton.h" #include "Styling/SlateBrush.h" #include "Styling/SlateIconFinder.h" #include "Styling/StyleColors.h" #include "Widgets/Images/SImage.h" #include "Widgets/Input/SCheckBox.h" #include "Widgets/Layout/SBorder.h" #include "Widgets/Layout/SBox.h" #include "Widgets/Layout/SSeparator.h" #include "Widgets/Layout/SSpacer.h" #include "Widgets/Layout/SSplitter.h" #include "Widgets/SBoxPanel.h" #include "Widgets/Text/STextBlock.h" #include "Widgets/Views/ITableRow.h" #include "Widgets/Views/SListView.h" #include "Widgets/Views/STableRow.h" #include "Widgets/Views/STableViewBase.h" #define LOCTEXT_NAMESPACE "InterchangeAssetCard" /************************************************************************/ /* SInterchangeAssetCard Implementation */ /************************************************************************/ SInterchangeAssetCard::~SInterchangeAssetCard() { } void SInterchangeAssetCard::RefreshCard(UInterchangeBaseNodeContainer* InPreviewNodeContainer) { check(InPreviewNodeContainer); CardAssetCount = 0; CardAssetToImportCount = 0; CardAssetDisabledCount = 0; CardTooltip.Reset(); FString ImportAssets; FString IgnoreAssets; auto FillStringData = [](FString& StringData, const FString& DisplayLabel) { StringData += TEXT("\n\t"); StringData += DisplayLabel; }; //Query the data we need to update the card InPreviewNodeContainer->IterateNodesOfType([this, &FillStringData, &ImportAssets, &IgnoreAssets](const FString& NodeUid, UInterchangeFactoryBaseNode* FactoryNode) { if (!FactoryNode || !FactoryNode->GetObjectClass() || !FactoryNode->GetObjectClass()->IsChildOf(AssetClass)) { return; } CardAssetCount++; if (FactoryNode->IsEnabled()) { FillStringData(ImportAssets, FactoryNode->GetDisplayLabel()); CardAssetToImportCount++; } else { FillStringData(IgnoreAssets, FactoryNode->GetDisplayLabel()); CardAssetDisabledCount++; } }); if (!ImportAssets.IsEmpty()) { CardTooltip += LOCTEXT("CardImportAssetTooltipPrefix", "Import Assets:").ToString(); CardTooltip += ImportAssets; } if (!IgnoreAssets.IsEmpty()) { CardTooltip += LOCTEXT("CardIgnoreAssetTooltipPrefix", "Ignore Assets:").ToString(); CardTooltip += IgnoreAssets; } } bool SInterchangeAssetCard::RefreshHasConflicts(const TArray& InConflictInfos) { for (const FInterchangeConflictInfo& ConflictInfo : InConflictInfos) { if (ConflictInfo.AffectedAssetClasses.Contains(AssetClass)) { bHasConflictWarnings = true; return true; } } bHasConflictWarnings = false; return false; } void SInterchangeAssetCard::Construct(const FArguments& InArgs) { //Make sure we have a valid node container check(InArgs._PreviewNodeContainer); AssetClass = InArgs._AssetClass; check(AssetClass != nullptr); ShouldImportAssetType = InArgs._ShouldImportAssetType; check(ShouldImportAssetType.IsBound()); OnImportAssetTypeChanged = InArgs._OnImportAssetTypeChanged; check(OnImportAssetTypeChanged.IsBound()); RefreshCard(InArgs._PreviewNodeContainer); const FSlateBrush* CardAssetIcon = nullptr; CardAssetIcon = FSlateIconFinder::FindIconBrushForClass(AssetClass); TSharedPtr CardIconWidget = SNew(SImage) .Image(CardAssetIcon) .Visibility(CardAssetIcon != FAppStyle::GetDefaultBrush() ? EVisibility::Visible : EVisibility::Collapsed); FText CardImportText = FText::Format(LOCTEXT("CardImportText", "Import {0}"), FText::FromString(AssetClass->GetName())); FName IconWarningName = "Icons.Alert.Solid"; const FSlateIcon IconWarning = FSlateIconFinder::FindIcon(IconWarningName); const ISlateStyle* InterchangeEditorPipelineStyle = FSlateStyleRegistry::FindSlateStyle("InterchangeEditorPipelineStyle"); const FSlateBrush* HeaderBorderBrush = nullptr; const FSlateBrush* BodyBorderBrush = nullptr; const FSlateBrush* BackgroundBorderBrush = nullptr; if (InterchangeEditorPipelineStyle) { HeaderBorderBrush = InterchangeEditorPipelineStyle->GetBrush("AssetCard.Header.Border"); BodyBorderBrush = InterchangeEditorPipelineStyle->GetBrush("AssetCard.Body.Border"); BackgroundBorderBrush = InterchangeEditorPipelineStyle->GetBrush("AssetCardList.Background.Border"); } ChildSlot [ SNew(SVerticalBox) .Visibility_Lambda([this]() { return CardAssetToImportCount > 0 ? EVisibility::Visible : EVisibility::Collapsed; }) + SVerticalBox::Slot() .AutoHeight() .Padding(0.0f, 4.0f, 0.0f, 0.0f) [ SNew(SBorder) .BorderImage(HeaderBorderBrush) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .VAlign(VAlign_Center) .HAlign(HAlign_Center) .AutoWidth() .Padding(8.0f, 4.0f, 4.0f, 4.0f) [ CardIconWidget.ToSharedRef() ] + SHorizontalBox::Slot() .VAlign(VAlign_Center) .HAlign(HAlign_Left) .AutoWidth() .Padding(4.0f, 4.0f, 8.0f, 4.0f) [ SNew(STextBlock) .Font(FAppStyle::GetFontStyle("NormalFont")) .Text_Lambda([this]() { return FText::Format(LOCTEXT("CardLabelText", "{0} ({1} {2})"), FText::FromString(AssetClass->GetName()), FText::FromString(FString::FromInt(CardAssetToImportCount)), CardAssetToImportCount > 1 ? LOCTEXT("CardAssetsPlural", "assets") : LOCTEXT("CardAssetSingle", "asset")); }) .ToolTipText_Lambda([this]() { return FText::FromString(CardTooltip); }) ] + SHorizontalBox::Slot() .FillWidth(1.0f) [ SNew(SSpacer) ] + SHorizontalBox::Slot() .AutoWidth() .Padding(8.0f, 4.0f, 8.0f, 4.0f) [ SNew(SHorizontalBox) .Visibility_Lambda([this]() {return bHasConflictWarnings ? EVisibility::Visible : EVisibility::Collapsed; }) .ToolTipText(LOCTEXT("ConflictWarningTooltipText", "There are some conflicts generated while importing the source file. Go to Conflicts Section in Advanced Settings for more details.")) + SHorizontalBox::Slot() .VAlign(VAlign_Center) .HAlign(HAlign_Center) .AutoWidth() [ SNew(SImage) .Image(IconWarning.GetOptionalIcon()) .ColorAndOpacity(FStyleColors::Warning) ] + SHorizontalBox::Slot() .VAlign(VAlign_Center) .HAlign(HAlign_Left) .AutoWidth() .Padding(4.0f, 4.0f, 8.0f, 4.0f) [ SNew(STextBlock) .Text(LOCTEXT("ConflictWarningText", "Conflict Warnings")) .ColorAndOpacity(FStyleColors::Warning) ] ] ] ] + SVerticalBox::Slot() .Padding(0.0f, 0.0f, 0.0f, 4.0f) .AutoHeight() [ SNew(SBorder) .BorderImage(BodyBorderBrush) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .FillWidth(0.6f) .HAlign(HAlign_Left) .Padding(8.0f, 4.0f) [ SNew(SBox) .Padding(0.0f) [ SNew(STextBlock) .Text(CardImportText) ] ] + SHorizontalBox::Slot() .Padding(0.0f) .AutoWidth() [ SNew(SSeparator) .Orientation(EOrientation::Orient_Vertical) .Thickness(1.0f) ] + SHorizontalBox::Slot() .FillWidth(0.4f) .HAlign(HAlign_Left) .Padding(8.0f, 4.0f) [ SNew(SBox) .Padding(0.) [ SNew(SCheckBox) .IsChecked_Lambda([this]() { if (ShouldImportAssetType.Execute()) { return ECheckBoxState::Checked; } return ECheckBoxState::Unchecked; }) .OnCheckStateChanged_Lambda([this](ECheckBoxState CheckBoxState) { OnImportAssetTypeChanged.Execute(CheckBoxState == ECheckBoxState::Checked); }) ] ] ] ] ]; } void SInterchangeAssetCardList::Construct(const FArguments& InArgs) { AssetCards = InArgs._AssetCards; check(AssetCards); AssetCardList = SNew(SListView>) .SelectionMode(ESelectionMode::None) .ListItemsSource(AssetCards) .OnGenerateRow(this, &SInterchangeAssetCardList::MakeAssetCardListRowWidget); const ISlateStyle* InterchangeEditorPipelineStyle = FSlateStyleRegistry::FindSlateStyle("InterchangeEditorPipelineStyle"); const FSlateBrush* BackgroundBorderBrush = nullptr; if (InterchangeEditorPipelineStyle) { BackgroundBorderBrush = InterchangeEditorPipelineStyle->GetBrush("AssetCardList.Background.Border"); } ChildSlot [ SNew(SBorder) .Padding(8.0f, 4.0f) .BorderImage(BackgroundBorderBrush) [ AssetCardList.ToSharedRef() ] ]; } void SInterchangeAssetCardList::RefreshList(UInterchangeBaseNodeContainer* InPreviewNodeContainer) { for (TSharedPtr AssetCard : *AssetCards) { AssetCard->RefreshCard(InPreviewNodeContainer); } AssetCardList->RequestListRefresh(); } TSharedRef SInterchangeAssetCardList::MakeAssetCardListRowWidget(TSharedPtr InElement, const TSharedRef& OwnerTable) { return SNew(STableRow>, OwnerTable) [ InElement.ToSharedRef() ]; } #undef LOCTEXT_NAMESPACE