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;
}