bool UCanvasPanel::GetGeometryForSlot(UCanvasPanelSlot* Slot, FGeometry& ArrangedGeometry) const { if ( Slot->Content == NULL ) { return false; } TSharedPtr<SConstraintCanvas> Canvas = GetCanvasWidget(); if ( Canvas.IsValid() ) { FArrangedChildren ArrangedChildren(EVisibility::All); Canvas->ArrangeChildren(Canvas->GetCachedGeometry(), ArrangedChildren); for ( int32 ChildIndex = 0; ChildIndex < ArrangedChildren.Num(); ChildIndex++ ) { if ( ArrangedChildren[ChildIndex].Widget == Slot->Content->TakeWidget() ) { ArrangedGeometry = ArrangedChildren[ChildIndex].Geometry; return true; } } } return false; }
FWeakWidgetPath::EPathResolutionResult::Result FWeakWidgetPath::ToWidgetPath( FWidgetPath& WidgetPath, EInterruptedPathHandling::Type InterruptedPathHandling, const FPointerEvent* PointerEvent ) const { SCOPE_CYCLE_COUNTER(STAT_ToWidgetPath); TArray<FWidgetAndPointer> PathWithGeometries; TArray< TSharedPtr<SWidget> > WidgetPtrs; // Convert the weak pointers into shared pointers because we are about to do something with this path instead of just observe it. TSharedPtr<SWindow> TopLevelWindowPtr = Window.Pin(); for( TArray< TWeakPtr<SWidget> >::TConstIterator SomeWeakWidgetPtr( Widgets ); SomeWeakWidgetPtr; ++SomeWeakWidgetPtr ) { WidgetPtrs.Add( SomeWeakWidgetPtr->Pin() ); } // The path can get interrupted if some subtree of widgets disappeared, but we still maintain weak references to it. bool bPathUninterrupted = false; // For each widget in the path compute the geometry. We are able to do this starting with the top-level window because it knows its own geometry. if ( TopLevelWindowPtr.IsValid() ) { bPathUninterrupted = true; FGeometry ParentGeometry = TopLevelWindowPtr->GetWindowGeometryInScreen(); PathWithGeometries.Add( FWidgetAndPointer( FArrangedWidget( TopLevelWindowPtr.ToSharedRef(), ParentGeometry ), // @todo slate: this should be the cursor's virtual position in window space. TSharedPtr<FVirtualPointerPosition>() ) ); FArrangedChildren ArrangedChildren(EVisibility::Visible, true); TSharedPtr<FVirtualPointerPosition> VirtualPointerPos; // For every widget in the vertical slice... for( int32 WidgetIndex = 0; bPathUninterrupted && WidgetIndex < WidgetPtrs.Num()-1; ++WidgetIndex ) { TSharedPtr<SWidget> CurWidget = WidgetPtrs[WidgetIndex]; bool bFoundChild = false; if ( CurWidget.IsValid() ) { // Arrange the widget's children to find their geometries. ArrangedChildren.Empty(); CurWidget->ArrangeChildren(ParentGeometry, ArrangedChildren); // Find the next widget in the path among the arranged children. for( int32 SearchIndex = 0; !bFoundChild && SearchIndex < ArrangedChildren.Num(); ++SearchIndex ) { FArrangedWidget& ArrangedWidget = ArrangedChildren[SearchIndex]; if ( ArrangedWidget.Widget == WidgetPtrs[WidgetIndex+1] ) { if( PointerEvent && !VirtualPointerPos.IsValid() ) { VirtualPointerPos = CurWidget->TranslateMouseCoordinateFor3DChild( ArrangedWidget.Widget, ParentGeometry, PointerEvent->GetScreenSpacePosition(), PointerEvent->GetLastScreenSpacePosition() ); } bFoundChild = true; // Remember the widget, the associated geometry, and the pointer position in a transformed space. PathWithGeometries.Add( FWidgetAndPointer(ArrangedChildren[SearchIndex], VirtualPointerPos) ); // The next child in the vertical slice will be arranged with respect to its parent's geometry. ParentGeometry = ArrangedChildren[SearchIndex].Geometry; } } } bPathUninterrupted = bFoundChild; if (!bFoundChild && InterruptedPathHandling == EInterruptedPathHandling::ReturnInvalid ) { return EPathResolutionResult::Truncated; } } } WidgetPath = FWidgetPath( PathWithGeometries ); return bPathUninterrupted ? EPathResolutionResult::Live : EPathResolutionResult::Truncated; }