// Copyright Epic Games, Inc. All Rights Reserved. #include "SMassProcessorsView.h" #include "SMassProcessor.h" #include "SMassProcessorsWidget.h" #include "Widgets/Layout/SScrollBox.h" #include "Widgets/Views/SListView.h" #include "Widgets/SBoxPanel.h" #define LOCTEXT_NAMESPACE "SMassDebugger" namespace UE::Mass::Debug::UI::Private { const FText PickProcessorLabel = FText::FromString(TEXT("Pick a processor from the list")); const FText MissingDebugData = FText::FromString(TEXT("Missing debug data")); } //----------------------------------------------------------------------// // SMassProcessorListTableRow //----------------------------------------------------------------------// class SMassProcessorListTableRow : public STableRow> { public: using Super = STableRow>; void Construct(const FArguments& InArgs, const TSharedRef& InOwnerTableView, const TSharedPtr& InEntryItem , TSharedRef DebuggerModel) { if (!InEntryItem.IsValid()) { return; } Item = InEntryItem; Super::Construct(Super::FArguments(), InOwnerTableView); ChildSlot [ SNew(SBox) .Padding(2.0f) [ SNew(SMassProcessorWidget, Item.ToSharedRef(), DebuggerModel) ] ]; } TSharedPtr Item; }; //----------------------------------------------------------------------// // SMassProcessorCollectionListView //----------------------------------------------------------------------// /** * we have multiple instances of SMassProcessorCollectionListView at one time, and we want selection * cleared on all of them when any of them gets cleared. This class lets us do it by overriding * Private_ClearSelection and notifying the main view about the fact. */ class SMassProcessorCollectionListView : public SListView> { public: using Super = SListView>; void Construct(const FArguments& InArgs, const TWeakPtr& InWeakMainView) { WeakMainView = InWeakMainView; Super::Construct(InArgs); } virtual void Private_ClearSelection() override { if (TSharedPtr SharedMainView = WeakMainView.Pin()) { SharedMainView->OnClearSelection(*this); } SListView::Private_ClearSelection(); } protected: TWeakPtr WeakMainView; }; //----------------------------------------------------------------------// // SMassProcessorCollectionTableRow //----------------------------------------------------------------------// class SMassProcessorCollectionTableRow : public STableRow> { public: using Super = STableRow>; using FItemType = TSharedPtr; void Construct(const FArguments&, const TSharedRef& InOwnerTableView, const TSharedPtr& InEntryItem , const TSharedRef& MainView, TSharedRef DebuggerModel) { CollectionItem = InEntryItem; Super::Construct(Super::FArguments(), InOwnerTableView); TSharedPtr& ProcessorsListWidget = MainView->ProcessorsListWidgets.AddDefaulted_GetRef(); ChildSlot [ SNew(SVerticalBox) + SVerticalBox::Slot() .AutoHeight() .VAlign(VAlign_Top) [ SNew(STextBlock) .Text(FText::FromName(CollectionItem->Label)) .TextStyle(FAppStyle::Get(), "LargeText") ] + SVerticalBox::Slot() .AutoHeight() .VAlign(VAlign_Top) [ SAssignNew(ProcessorsListWidget, SMassProcessorCollectionListView, MainView) .ListItemsSource(&CollectionItem->Container) .SelectionMode(ESelectionMode::None) .OnSelectionChanged(MainView->OnProcessorSelectionChanged) .OnGenerateRow_Lambda([DebuggerModel](FItemType Item, const TSharedRef& OwnerTable) { return SNew(SMassProcessorListTableRow, OwnerTable, Item, DebuggerModel); }) ] ]; } protected: TSharedPtr CollectionItem; }; //----------------------------------------------------------------------// // SMassProcessorsView //----------------------------------------------------------------------// void SMassProcessorsView::Construct(const FArguments& InArgs, const TSharedRef& InDebuggerModel) { Initialize(InDebuggerModel); ChildSlot [ SNew(SSplitter) .Orientation(Orient_Horizontal) + SSplitter::Slot() .Value(.35f) .MinSize(260.0f) [ SNew(SScrollBox) .Orientation(Orient_Vertical) + SScrollBox::Slot() .VAlign(VAlign_Top) [ SAssignNew(ProcessorCollectionsListWidget, SListView>) .ListItemsSource(&DebuggerModel->CachedProcessorCollections) .SelectionMode(ESelectionMode::None) .Orientation(Orient_Horizontal) .OnGenerateRow_Lambda([SharedThis = StaticCastSharedRef(AsShared()), InDebuggerModel] (TSharedPtr Item, const TSharedRef& OwnerTable) { return SNew(SMassProcessorCollectionTableRow, OwnerTable, Item, SharedThis, InDebuggerModel); }) ] ] ]; PopulateProcessorList(); } void SMassProcessorsView::ProcessorListSelectionChanged(TSharedPtr SelectedItem, ESelectInfo::Type SelectInfo) { if (SelectInfo == ESelectInfo::Direct) { return; } check(DebuggerModel); TArray> CurrentlySelectedProcessors; for (const auto& Widget : ProcessorsListWidgets) { TArray> LocalSelectedProcessors; Widget->GetSelectedItems(LocalSelectedProcessors); CurrentlySelectedProcessors.Append(MoveTemp(LocalSelectedProcessors)); } DebuggerModel->SelectProcessors(CurrentlySelectedProcessors, SelectInfo); } void SMassProcessorsView::OnClearSelection(const SMassProcessorCollectionListView& TransientSource) { if (bClearingSelection) { return; } TGuardValue GuardValue(bClearingSelection, true); for (const auto& Widget : ProcessorsListWidgets) { if (Widget.Get() != &TransientSource) { Widget->ClearSelection(); } } } void SMassProcessorsView::OnProcessorsSelected(TConstArrayView> SelectedProcessors, ESelectInfo::Type SelectInfo) { using namespace UE::Mass::Debug::UI::Private; using namespace UE::Mass::Debug; if (!DebuggerModel) { return; } if (SelectInfo == ESelectInfo::Direct) { for (const auto& Widget : ProcessorsListWidgets) { Widget->ClearSelection(); } } if (SelectedProcessors.Num()) { if (SelectInfo == ESelectInfo::Direct) { for (const auto& Widget : ProcessorsListWidgets) { Widget->SetItemSelection(SelectedProcessors, /*bSelected=*/true, ESelectInfo::OnMouseClick); } } } ProcessorCollectionsListWidget->RequestListRefresh(); } void SMassProcessorsView::OnArchetypesSelected(TConstArrayView> SelectedArchetypes, ESelectInfo::Type SelectInfo) { OnProcessorsSelected(DebuggerModel->SelectedProcessors, ESelectInfo::Direct); } void SMassProcessorsView::OnRefresh() { PopulateProcessorList(); } void SMassProcessorsView::PopulateProcessorList() { check(DebuggerModel.IsValid()); DebuggerModel->ClearProcessorSelection(); ProcessorCollectionsListWidget->RequestListRefresh(); } #undef LOCTEXT_NAMESPACE