static FEndOfListResult ComputeOffsetForEndOfList( const FGeometry& ListPanelGeometry, const FChildren& ListPanelChildren )
{
	float OffsetFromEndOfList = 0.0f;
	float AvailableSpace = ListPanelGeometry.Size.Y;
	float ItemsAboveView = 0.0f;
	for ( int ChildIndex=ListPanelChildren.Num()-1; ChildIndex >= 0; --ChildIndex )
	{
		const float CurChildHeight = ListPanelChildren.GetChildAt(ChildIndex)->GetDesiredSize().Y;
		if (AvailableSpace == 0)
		{
			ItemsAboveView ++;
		}

		if ( CurChildHeight < AvailableSpace )
		{
			// This whole child fits
			OffsetFromEndOfList += 1;
			AvailableSpace -= CurChildHeight;
		}
		else
		{
			OffsetFromEndOfList += AvailableSpace / CurChildHeight;
			ItemsAboveView += (CurChildHeight - AvailableSpace)/CurChildHeight;
			AvailableSpace = 0;
		}
	}

	return FEndOfListResult( OffsetFromEndOfList, ItemsAboveView );
}
void SWidget::SlatePrepass(float LayoutScaleMultiplier)
{
	//SLATE_CYCLE_COUNTER_SCOPE_CUSTOM_DETAILED(SLATE_STATS_DETAIL_LEVEL_MED, GSlatePrepass, GetType());

	// TODO Figure out a better way than to just reset the pointer.  This causes problems when we prepass
	// volatile widgets, who still need to know about their invalidation panel incase they vanish themselves.

	// Reset the layout cache object each pre-pass to ensure we never access a stale layout cache object 
	// as this widget could have been moved in and out of a panel that was invalidated between frames.
	//LayoutCache = nullptr;

	if ( bCanHaveChildren )
	{
		// Cache child desired sizes first. This widget's desired size is
		// a function of its children's sizes.
		FChildren* MyChildren = this->GetChildren();
		int32 NumChildren = MyChildren->Num();
		for ( int32 ChildIndex=0; ChildIndex < NumChildren; ++ChildIndex )
		{
			const TSharedRef<SWidget>& Child = MyChildren->GetChildAt(ChildIndex);

			if ( Child->Visibility.Get() != EVisibility::Collapsed )
			{
				const float ChildLayoutScaleMultiplier = GetRelativeLayoutScale(MyChildren->GetSlotAt(ChildIndex));
				// Recur: Descend down the widget tree.
				Child->SlatePrepass(LayoutScaleMultiplier*ChildLayoutScaleMultiplier);
			}
		}
	}

	// Cache this widget's desired size.
	CacheDesiredSize(LayoutScaleMultiplier);
}
static PyObject *py_ue_swidget_get_children(ue_PySWidget *self, PyObject * args)
{
	FChildren *children = self->Widget->GetChildren();
	PyObject *py_list = PyList_New(0);
	for (int32 i = 0; i < children->Num(); i++)
	{
		TSharedRef<SWidget> widget = children->GetChildAt(i);
		PyObject *item = (PyObject *)ue_py_get_swidget(widget);
		PyList_Append(py_list, item);
		Py_DECREF(item);
	}
	return py_list;
}
void SWidget::CachePrepass(ILayoutCache* InLayoutCache)
{
	if ( bCanHaveChildren )
	{
		FChildren* MyChildren = this->GetChildren();
		int32 NumChildren = MyChildren->Num();
		for ( int32 ChildIndex=0; ChildIndex < NumChildren; ++ChildIndex )
		{
			const TSharedRef<SWidget>& Child = MyChildren->GetChildAt(ChildIndex);
			if ( Child->GetVisibility().IsVisible() == false )
			{
				Child->LayoutCache = InLayoutCache;
			}
			else
			{
				Child->CachePrepass(InLayoutCache);
			}
		}
	}
}
TSharedPtr<class SWidget> GetFirstKeyboardFocusableWidget( TSharedPtr<class SWidget> FocusCandidate )
{
	if ( FocusCandidate->SupportsKeyboardFocus() )
	{
		return FocusCandidate;
	}

	FChildren * Children = FocusCandidate->GetChildren();

	if ( Children != NULL )
	{
		for ( int32 i = 0; i < Children->Num(); i++ )
		{
			FocusCandidate = GetFirstKeyboardFocusableWidget( Children->GetChildAt( i ) );

			if ( FocusCandidate.IsValid() )
			{
				return FocusCandidate;
			}
		}
	}

	return NULL;
}