// Copyright Epic Games, Inc. All Rights Reserved. #include "SRewindDebuggerTrackTree.h" #include "ISequencerWidgetsModule.h" #include "ObjectTrace.h" #include "RewindDebugger.h" #include "RewindDebuggerStyle.h" #include "Styling/SlateIconFinder.h" #include "Widgets/Images/SImage.h" #include "Widgets/Images/SLayeredImage.h" #define LOCTEXT_NAMESPACE "SAnimationInsights" class SRewindDebuggerComponentTreeTableRow final : public STableRow> { public: SLATE_BEGIN_ARGS(SRewindDebuggerComponentTreeTableRow) {} SLATE_END_ARGS() void Construct(const FArguments& InArgs, const TSharedRef& InOwnerTableView) { STableRow>::Construct(STableRow>::FArguments(), InOwnerTableView); Style = &FRewindDebuggerStyle::Get().GetWidgetStyle("RewindDebugger.TableRow"); SetHover(TAttribute::CreateLambda([this]() { if (TSharedPtr>> TableView = OwnerTablePtr.Pin()) { if (const TSharedPtr* Track = GetItemForThis(TableView.ToSharedRef())) { return (*Track)->GetIsHovered(); } } return false; })); } virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override { if (TSharedPtr>> TableView = OwnerTablePtr.Pin()) { if (const TSharedPtr* Track = GetItemForThis(TableView.ToSharedRef())) { (*Track)->SetIsTreeHovered(true); } } STableRow>::OnMouseEnter(MyGeometry, MouseEvent); } virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override { STableRow>::OnMouseLeave(MouseEvent); if (TSharedPtr>> TableView = OwnerTablePtr.Pin()) { if (const TSharedPtr* Track = GetItemForThis(TableView.ToSharedRef())) { (*Track)->SetIsTreeHovered(false); } } } }; TSharedRef SRewindDebuggerTrackTree::TreeViewGenerateRow(TSharedPtr InItem, const TSharedRef& OwnerTable) const { const FSlateIcon ObjectIcon = InItem->GetIcon(); const TSharedRef LayeredIcons = SNew(SLayeredImage) .DesiredSizeOverride(FVector2D(16, 16)) .Image(ObjectIcon.GetIcon()); if (ObjectIcon.GetOverlayIcon()) { LayeredIcons->AddLayer(ObjectIcon.GetOverlayIcon()); } TSharedRef Row = SNew(SRewindDebuggerComponentTreeTableRow, OwnerTable); Row->SetContent( SNew(SHorizontalBox) + SHorizontalBox::Slot().AutoWidth().Padding(2) [ LayeredIcons ] + SHorizontalBox::Slot() .FillWidth(1.0f) .Padding(1.0f, 0.0f) .VAlign(VAlign_Center) [ SNew(STextBlock) .Text(InItem->GetDisplayName()) .Font_Lambda([this, InItem]() { return InItem->GetIsHovered() ? FCoreStyle::GetDefaultFontStyle("Bold", 10) : FCoreStyle::GetDefaultFontStyle("Regular", 10); }) ] ); return Row; } void TreeViewGetChildren(TSharedPtr InItem, TArray>& OutChildren) { InItem->IterateSubTracks([&OutChildren](const TSharedPtr& Track) { if (Track->IsVisible()) { OutChildren.Add(Track); } }); } void SRewindDebuggerTrackTree::TreeViewExpansionChanged(TSharedPtr InItem, const bool bShouldBeExpanded) const { InItem->SetIsExpanded(bShouldBeExpanded); OnExpansionChanged.ExecuteIfBound(); } void SRewindDebuggerTrackTree::SetSelection(const TSharedPtr& SelectedItem) const { TreeView->SetSelection(SelectedItem); } void SRewindDebuggerTrackTree::ScrollTo(const double ScrollOffset) const { TreeView->SetScrollOffset(ScrollOffset); } void SRewindDebuggerTrackTree::Construct(const FArguments& InArgs) { Tracks = InArgs._Tracks; TreeView = SNew(STreeView>) .TreeItemsSource(Tracks) .OnGenerateRow(this, &SRewindDebuggerTrackTree::TreeViewGenerateRow) .OnGetChildren_Static(&TreeViewGetChildren) .OnExpansionChanged(this, &SRewindDebuggerTrackTree::TreeViewExpansionChanged) .SelectionMode(ESelectionMode::Single) .OnSelectionChanged(InArgs._OnSelectionChanged) .OnMouseButtonDoubleClick(InArgs._OnMouseButtonDoubleClick) .ExternalScrollbar(InArgs._ExternalScrollBar) .AllowOverscroll(EAllowOverscroll::No) .OnTreeViewScrolled(InArgs._OnScrolled) .ScrollbarDragFocusCause(EFocusCause::SetDirectly) .OnContextMenuOpening(InArgs._OnContextMenuOpening); ChildSlot [ TreeView.ToSharedRef() ]; OnExpansionChanged = InArgs._OnExpansionChanged; } static void RestoreExpansion(const TSharedPtr& Track, TSharedPtr>>& TreeView) { TreeView->SetItemExpansion(Track, Track->GetIsExpanded()); Track->IterateSubTracks([&TreeView](const TSharedPtr& SubTrack) { RestoreExpansion(SubTrack, TreeView); }); } void SRewindDebuggerTrackTree::RestoreExpansion() { for (TSharedPtr& Track : *Tracks) { ::RestoreExpansion(Track, TreeView); } } void SRewindDebuggerTrackTree::Refresh() { TreeView->RebuildList(); if (Tracks) { // make sure any newly added TreeView nodes are created expanded RestoreExpansion(); } } #undef LOCTEXT_NAMESPACE