static bool FindWidgetsUnderPoint(const FVector2D& InHitTestPoint, const FVector2D& InWindowPosition, const TSharedRef<FWidgetReflectorNodeBase>& InWidget, TArray<TSharedRef<FWidgetReflectorNodeBase>>& OutWidgets) { const bool bNeedsHitTesting = InWidget->GetHitTestInfo().IsHitTestVisible || InWidget->GetHitTestInfo().AreChildrenHitTestVisible; if (bNeedsHitTesting) { const FSlateRect HitTestRect = FSlateRect::FromPointAndExtent( InWidget->GetAccumulatedLayoutTransform().GetTranslation() - InWindowPosition, TransformPoint(InWidget->GetAccumulatedLayoutTransform().GetScale(), InWidget->GetLocalSize()) ); if (HitTestRect.ContainsPoint(InHitTestPoint)) { OutWidgets.Add(InWidget); if (InWidget->GetHitTestInfo().AreChildrenHitTestVisible) { for (const auto& ChildWidget : InWidget->GetChildNodes()) { if (FindWidgetsUnderPoint(InHitTestPoint, InWindowPosition, ChildWidget, OutWidgets)) { return true; } } } return InWidget->GetHitTestInfo().IsHitTestVisible; } } return false; }
void SSequencerTrackArea::GenerateLayoutNodeWidgetsRecursive( const TArray< TSharedRef<FSequencerDisplayNode> >& Nodes ) { for( int32 NodeIndex = 0; NodeIndex < Nodes.Num(); ++NodeIndex ) { TSharedRef<FSequencerDisplayNode> Node = Nodes[NodeIndex]; // The section area encompasses multiple logical child nodes so we do not generate children that arent section areas (they would not be top level nodes in that case) if( Node->GetType() == ESequencerNode::Track ) { GenerateWidgetForNode( Node ); GenerateLayoutNodeWidgetsRecursive( Node->GetChildNodes() ); } } }
void SAnimationOutlinerView::GenerateWidgetForNode( TSharedRef<FSequencerDisplayNode>& InLayoutNode ) { Children.Add( SNew( SAnimationOutlinerTreeNode, InLayoutNode) .OnSelectionChanged( this, &SAnimationOutlinerView::OnSelectionChanged ) ); // Object nodes do not generate widgets for their children if( InLayoutNode->GetType() != ESequencerNode::Object ) { const TArray< TSharedRef<FSequencerDisplayNode> >& ChildNodes = InLayoutNode->GetChildNodes(); for( int32 ChildIndex = 0; ChildIndex < ChildNodes.Num(); ++ChildIndex ) { TSharedRef<FSequencerDisplayNode> ChildNode = ChildNodes[ChildIndex]; GenerateWidgetForNode( ChildNode ); } } }
/** * Recursively filters nodes * * @param StartNode The node to start from * @param FilterStrings The filter strings which need to be matched * @param OutFilteredNodes The list of all filtered nodes */ static bool FilterNodesRecursive( const TSharedRef<FSequencerDisplayNode>& StartNode, const TArray<FString>& FilterStrings, TSet< TSharedRef< const FSequencerDisplayNode> >& OutFilteredNodes ) { // Assume the filter is acceptable bool bFilterAcceptable = true; // Check each string in the filter strings list against for (int32 TestNameIndex = 0; TestNameIndex < FilterStrings.Num(); ++TestNameIndex) { const FString& TestName = FilterStrings[TestNameIndex]; if ( !StartNode->GetDisplayName().ToString().Contains( TestName ) ) { bFilterAcceptable = false; break; } } // Whether or the start node is in the filter bool bInFilter = false; if( bFilterAcceptable ) { // This node is now filtered OutFilteredNodes.Add( StartNode ); bInFilter = true; } // Check each child node to determine if it is filtered const TArray< TSharedRef<FSequencerDisplayNode> >& ChildNodes = StartNode->GetChildNodes(); for( int32 ChildIndex = 0; ChildIndex < ChildNodes.Num(); ++ChildIndex ) { // Mark the parent as filtered if any child node was filtered bFilterAcceptable |= FilterNodesRecursive( ChildNodes[ChildIndex], FilterStrings, OutFilteredNodes ); if( bFilterAcceptable && !bInFilter ) { OutFilteredNodes.Add( StartNode ); bInFilter = true; } } return bFilterAcceptable; }
void SSequencerTrackArea::Update( TSharedPtr<FSequencerNodeTree> InSequencerNodeTree ) { ScrollBox->ClearChildren(); const TArray< TSharedRef<FSequencerDisplayNode> >& RootNodes = InSequencerNodeTree->GetRootNodes(); for( int32 RootNodeIndex = 0; RootNodeIndex < RootNodes.Num(); ++RootNodeIndex ) { TSharedRef<FSequencerDisplayNode> RootNode = RootNodes[RootNodeIndex]; // Generate a widget for each root node GenerateWidgetForNode( RootNode ); // Generate a node for each children of the root node GenerateLayoutNodeWidgetsRecursive( RootNode->GetChildNodes() ); } // @todo Sequencer - Remove this expensive operation ScrollBox->SlatePrepass(); CurveEditor->SetSequencerNodeTree(InSequencerNodeTree); }