int32 SARResourceBarWidget::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
	const FSlateBrush* BrushResource = new FSlateBrush();
	
	FSlateDrawElement::MakeBox(
		OutDrawElements,
		LayerId,
		AllottedGeometry.ToPaintGeometry(),
		BrushResource,
		MyClippingRect,
		ESlateDrawEffect::None,
		FLinearColor::Gray * 0.35f
		);
	if (MyAttrComp.IsValid())
	{
		FVector2D WidgetSize = MyClippingRect.GetSize();
		//float HealthWidth = (MyAttrComp->Health * WidgetSize.X) / MyAttrComp->MaxHealth;
		float HealthWidth = (CurrentValue.Get() * WidgetSize.X) / MaxValue.Get();
		// Draw current health
		FSlateDrawElement::MakeBox(
			OutDrawElements,
			LayerId,
			AllottedGeometry.ToPaintGeometry(FVector2D::ZeroVector, FVector2D(HealthWidth, WidgetSize.Y)),
			BrushResource,
			MyClippingRect,
			ESlateDrawEffect::None,
			FLinearColor::Red *.9f
			);
	}

	return SCompoundWidget::OnPaint(Args, AllottedGeometry, MyClippingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
}
void FHittestGrid::BeginFrame( const FSlateRect& HittestArea )
{
	//LogGrid();

	GridOrigin = HittestArea.GetTopLeft();
	const FVector2D GridSize = HittestArea.GetSize();
	NumCells = FIntPoint( FMath::CeilToInt(GridSize.X / CellSize.X), FMath::CeilToInt(GridSize.Y / CellSize.Y) );
	WidgetsCachedThisFrame->Empty();
	Cells.Reset( NumCells.X * NumCells.Y );	
	Cells.SetNum( NumCells.X * NumCells.Y );
}
TSharedPtr<FTabManager::FLayoutNode> SDockingArea::GatherPersistentLayout() const
{
	// Assume that all the nodes were dragged out, and there's no meaningful layout data to be gathered.
	bool bHaveLayoutData = false;

	TSharedPtr<FTabManager::FArea> PersistentNode;

	TSharedPtr<SWindow> ParentWindow = ParentWindowPtr.Pin();
	if ( ParentWindow.IsValid() && bManageParentWindow )
	{
		FSlateRect WindowRect = ParentWindow->GetNonMaximizedRectInScreen();

		// In order to restore SWindows to their correct size, we need to save areas as 
		// client area sizes, since the Constructor for SWindow uses a client size
		if (!ParentWindow->HasOSWindowBorder())
		{
			const FMargin WindowBorder = ParentWindow->GetWindowBorderSize();
			WindowRect.Right -= WindowBorder.Left + WindowBorder.Right;
			WindowRect.Bottom -= WindowBorder.Top + WindowBorder.Bottom;
		}

		PersistentNode = FTabManager::NewArea( WindowRect.GetSize() );
		PersistentNode->SetWindow( FVector2D( WindowRect.Left, WindowRect.Top ), ParentWindow->IsWindowMaximized() );
	}
	else
	{
		// An area without a window persists because it must be a primary area.
		// Those must always be restored, even if they are empty.
		PersistentNode = FTabManager::NewPrimaryArea();
		bHaveLayoutData = true;
	}	

	PersistentNode->SetOrientation( this->GetOrientation() );

	for (int32 ChildIndex=0; ChildIndex < Children.Num(); ++ChildIndex)
	{
		TSharedPtr<FTabManager::FLayoutNode> PersistentChild = Children[ChildIndex]->GatherPersistentLayout();
		if ( PersistentChild.IsValid() )
		{
			bHaveLayoutData = true;
			PersistentNode->Split( PersistentChild.ToSharedRef() );
		}
	}

	if( !bHaveLayoutData )
	{
		PersistentNode.Reset();
	}

	return PersistentNode;
}
Exemple #4
0
int32 SPanel::PaintArrangedChildren( const FPaintArgs& Args, const FArrangedChildren& ArrangedChildren, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled  ) const
{
	// Because we paint multiple children, we must track the maximum layer id that they produced in case one of our parents
	// wants to an overlay for all of its contents.
	int32 MaxLayerId = LayerId;

	for (int32 ChildIndex = 0; ChildIndex < ArrangedChildren.Num(); ++ChildIndex)
	{
		const FArrangedWidget& CurWidget = ArrangedChildren[ChildIndex];
		FSlateRect ChildClipRect = MyClippingRect.IntersectionWith(CurWidget.Geometry.GetClippingRect());
		
		if (ChildClipRect.GetSize().Size() > 0)
		{
			const int32 CurWidgetsMaxLayerId = CurWidget.Widget->Paint(Args.WithNewParent(this), CurWidget.Geometry, ChildClipRect, OutDrawElements, LayerId, InWidgetStyle, ShouldBeEnabled(bParentEnabled));
			MaxLayerId = FMath::Max(MaxLayerId, CurWidgetsMaxLayerId);
		}		
		
	}
	
	return MaxLayerId;
}
int32 SSplitter::GetHandleBeingResizedFromMousePosition( float PhysicalSplitterHandleSize, float HitDetectionSplitterHandleSize, FVector2D LocalMousePos, const TArray<FLayoutGeometry>& ChildGeometries )
{
	const int32 AxisIndex = (SplitterOrientation == Orient_Horizontal) ? 0 : 1;
	const float HalfHitDetectionSplitterHandleSize = ( HitDetectionSplitterHandleSize / 2 );
	const float HalfPhysicalSplitterHandleSize = ( PhysicalSplitterHandleSize / 2 );

	// Search for the two widgets between which the cursor currently resides.
	for ( int32 ChildIndex = 1; ChildIndex < ChildGeometries.Num(); ++ChildIndex )
	{
		FSlateRect PrevChildRect = ChildGeometries[ChildIndex - 1].GetRectInParentSpace();
		FVector2D NextChildOffset = ChildGeometries[ChildIndex].GetOffsetInParentSpace();
		float PrevBound = PrevChildRect.GetTopLeft().Component(AxisIndex) + PrevChildRect.GetSize().Component(AxisIndex) - HalfHitDetectionSplitterHandleSize + HalfPhysicalSplitterHandleSize;
		float NextBound = NextChildOffset.Component(AxisIndex) + HalfHitDetectionSplitterHandleSize - HalfPhysicalSplitterHandleSize;

		if ( LocalMousePos.Component(AxisIndex) > PrevBound && LocalMousePos.Component(AxisIndex) < NextBound )
		{
			return ChildIndex - 1;
		}
	}

	return INDEX_NONE;
}
void SProfilerThreadView::DrawUIStackNodes() const
{
//	SCOPE_LOG_TIME_FUNC();
	check( PaintState );
	const double ThreadViewOffsetPx = PositionXMS*NumPixelsPerMillisecond;
	PaintState->LayerId++;

	static const FSlateBrush* BorderBrush = FEditorStyle::GetBrush( "Profiler.ThreadView.SampleBorder" );
	const FColor GameThreadColor = FColorList::Red;
	const FColor RenderThreadColor = FColorList::Blue;
	const FColor ThreadColors[2] = {GameThreadColor, RenderThreadColor};

	// Draw nodes.
	for( const auto& RowOfNodes : ProfilerUIStream.LinearRowsOfNodes )
	{
		int32 NodeIndex = 0;
		for( const auto& UIStackNode : RowOfNodes )
		{
			NodeIndex++;
			// Check if the node is visible.
			//if( UIStackNode->IsVisible() )
			{
				const FVector2D PositionPx = UIStackNode->GetLocalPosition( ThreadViewOffsetPx, PositionY ) * FVector2D( 1.0f, NUM_PIXELS_PER_ROW );
				const FVector2D SizePx = FVector2D( FMath::Max( UIStackNode->WidthPx - 1.0, 0.0 ), NUM_PIXELS_PER_ROW );
				const FSlateRect ClippedNodeRect = PaintState->LocalClippingRect.IntersectionWith( FSlateRect( PositionPx, PositionPx + SizePx ) );

				// Check if this node is inside the visible area.
				if( ClippedNodeRect.IsEmpty() )
				{
					continue;
				}

				FColor NodeColor = UIStackNode->bIsCombined ? ThreadColors[UIStackNode->ThreadIndex].WithAlpha( 64 ) : ThreadColors[UIStackNode->ThreadIndex].WithAlpha( 192 );
				NodeColor.G += NodeIndex % 2 ? 0 : 64;

				// Draw a cycle counter for this profiler UI stack node.
				FSlateDrawElement::MakeBox
				(
					PaintState->OutDrawElements,
					PaintState->LayerId,
					PaintState->AllottedGeometry.ToPaintGeometry( ClippedNodeRect.GetTopLeft(), ClippedNodeRect.GetSize() ),
					BorderBrush,
					PaintState->AbsoluteClippingRect,
					PaintState->DrawEffects,
					NodeColor
				);
			}
		}
	}

	// @TODO yrx 2014-04-29 Separate layer for makebox, makeshadowtext, maketext.
	PaintState->LayerId++;

	const float MarkerPosYOffsetPx = ((float)NUM_PIXELS_PER_ROW - PaintState->SummaryFont8Height)*0.5f;
	
	// Draw nodes' descriptions.
	for( const auto& RowOfNodes : ProfilerUIStream.LinearRowsOfNodes )
	{
		for( const auto& UIStackNode : RowOfNodes )
		{
			const FVector2D PositionPx = UIStackNode->GetLocalPosition( ThreadViewOffsetPx, PositionY ) * FVector2D( 1.0f, NUM_PIXELS_PER_ROW );
			const FVector2D SizePx = FVector2D( UIStackNode->WidthPx, NUM_PIXELS_PER_ROW );
			const FSlateRect ClippedNodeRect = PaintState->LocalClippingRect.IntersectionWith( FSlateRect( PositionPx, PositionPx + SizePx ) );

			// Check if this node is inside the visible area.
			if( ClippedNodeRect.IsEmpty() )
			{
				continue;
			}

			FString StringStatName = UIStackNode->StatName.GetPlainNameString();
			FString StringStatNameWithTime = StringStatName + FString::Printf( TEXT( " (%.4f MS)" ), UIStackNode->GetDurationMS() );
			if( UIStackNode->bIsCulled )
			{
				StringStatName += TEXT( " [C]" );
				StringStatNameWithTime += TEXT( " [C]" );
			}

			// Update position of the text to be always visible and try to center it.
			const float StatNameWidthPx = PaintState->FontMeasureService->Measure( StringStatName, PaintState->SummaryFont8 ).X;
			const float StatNameWithTimeWidthPx = PaintState->FontMeasureService->Measure( StringStatNameWithTime, PaintState->SummaryFont8 ).X;
			const float TextAreaWidthPx = ClippedNodeRect.GetSize().X;

			bool bUseShortVersion = true;
			FVector2D AdjustedPositionPx;
			// Center the stat name with timing if we can.
			if( TextAreaWidthPx > StatNameWithTimeWidthPx )
			{
				AdjustedPositionPx = FVector2D( ClippedNodeRect.Left + (TextAreaWidthPx - StatNameWithTimeWidthPx)*0.5f, PositionPx.Y + MarkerPosYOffsetPx );
				bUseShortVersion = false;
			}
			// Center the stat name.
			else if( TextAreaWidthPx > StatNameWidthPx )
			{
				AdjustedPositionPx = FVector2D( ClippedNodeRect.Left + (TextAreaWidthPx - StatNameWidthPx)*0.5f, PositionPx.Y + MarkerPosYOffsetPx );
			}
			// Move to the edge.
			else
			{
				AdjustedPositionPx = FVector2D( ClippedNodeRect.Left, PositionPx.Y + MarkerPosYOffsetPx );
			}

			const FVector2D AbsolutePositionPx = PaintState->AllottedGeometry.LocalToAbsolute( ClippedNodeRect.GetTopLeft() );
			const FSlateRect AbsoluteClippingRect = FSlateRect( AbsolutePositionPx, AbsolutePositionPx + ClippedNodeRect.GetSize() );
			
			DrawText( bUseShortVersion ? StringStatName : StringStatNameWithTime, PaintState->SummaryFont8, AdjustedPositionPx, FColorList::White, FColorList::Black, FVector2D( 1.0f, 1.0f ), &AbsoluteClippingRect );
		}
	}
}
void SProfilerThreadView::DrawFramesBackgroundAndTimelines() const
{
	static const FSlateColorBrush SolidWhiteBrush = FSlateColorBrush( FColorList::White );

	check( PaintState );
	const double ThreadViewOffsetPx = PositionXMS*NumPixelsPerMillisecond;
	PaintState->LayerId++;
	TArray<FVector2D> LinePoints;

	// Draw frames background for easier reading.
	for( const auto& ThreadNode : ProfilerUIStream.ThreadNodes )
	{
		if( ThreadNode.StatName == NAME_GameThread )
		{
			const FVector2D PositionPx = ThreadNode.GetLocalPosition( ThreadViewOffsetPx, -1.0f );
			const FVector2D SizePx = FVector2D( ThreadNode.WidthPx, PaintState->Size2D().Y );

			const FSlateRect ClippedFrameBackgroundRect = PaintState->LocalClippingRect.IntersectionWith( FSlateRect( PositionPx, PositionPx + SizePx ) );

			FSlateDrawElement::MakeBox
			(
				PaintState->OutDrawElements,
				PaintState->LayerId,
				PaintState->AllottedGeometry.ToPaintGeometry( ClippedFrameBackgroundRect.GetTopLeft(), ClippedFrameBackgroundRect.GetSize() ),
				&SolidWhiteBrush,
				PaintState->AbsoluteClippingRect,
				PaintState->DrawEffects,
				ThreadNode.FrameIndex % 2 ? FColorList::White.WithAlpha( 64 ) : FColorList::White.WithAlpha( 128 )
			);

			// Check if this frame time marker is inside the visible area.
			const float LocalPositionXPx = PositionPx.X + SizePx.X;
			if( LocalPositionXPx < 0.0f || LocalPositionXPx > PaintState->Size2D().X )
			{
				continue;
			}

			LinePoints.Reset( 2 );
			LinePoints.Add( FVector2D( LocalPositionXPx, 0.0f ) );
			LinePoints.Add( FVector2D( LocalPositionXPx, PaintState->Size2D().Y ) );

			// Draw frame time marker.
			FSlateDrawElement::MakeLines
			(
				PaintState->OutDrawElements,
				PaintState->LayerId,
				PaintState->AllottedGeometry.ToPaintGeometry(),
				LinePoints,
				PaintState->AbsoluteClippingRect,
				PaintState->DrawEffects,
				PaintState->WidgetStyle.GetColorAndOpacityTint() * FColorList::SkyBlue,
				false
			);
		}
	}

	PaintState->LayerId++;

	const double PositionXStartPx = FMath::TruncToFloat( PositionXMS*NumPixelsPerMillisecond / (double)NUM_PIXELS_BETWEEN_TIMELINE )*(double)NUM_PIXELS_BETWEEN_TIMELINE;
	const double PositionXEndPx = PositionXStartPx + RangeXMS*NumPixelsPerMillisecond;

	for( double TimelinePosXPx = PositionXStartPx; TimelinePosXPx < PositionXEndPx; TimelinePosXPx += (double)NUM_PIXELS_BETWEEN_TIMELINE )
	{
		LinePoints.Reset( 2 );
		LinePoints.Add( FVector2D( TimelinePosXPx - ThreadViewOffsetPx, 0.0f ) );
		LinePoints.Add( FVector2D( TimelinePosXPx - ThreadViewOffsetPx, PaintState->Size2D().Y ) );

		// Draw time line.
		FSlateDrawElement::MakeLines
		(
			PaintState->OutDrawElements,
			PaintState->LayerId,
			PaintState->AllottedGeometry.ToPaintGeometry(),
			LinePoints,
			PaintState->AbsoluteClippingRect,
			PaintState->DrawEffects,
			PaintState->WidgetStyle.GetColorAndOpacityTint() * FColorList::LimeGreen,
			false
		);
	}
}
void FMainFrameHandler::ShutDownEditor()
{
	FEditorDelegates::OnShutdownPostPackagesSaved.Broadcast();

	// Any pending autosaves should not happen.  A tick will go by before the editor shuts down and we want to avoid auto-saving during this time.
	GUnrealEd->GetPackageAutoSaver().ResetAutoSaveTimer();
	GEditor->RequestEndPlayMap();

	// End any play on console/PC games still happening
	GEditor->EndPlayOnLocalPc();

	// Cancel any current Launch On in progress
	GEditor->CancelPlayingViaLauncher();

	TSharedPtr<SWindow> RootWindow = RootWindowPtr.Pin();

	// Save root window placement so we can restore it.
	if (RootWindow.IsValid())
	{
		FSlateRect WindowRect = RootWindow->GetNonMaximizedRectInScreen();
		FRootWindowLocation RootWindowLocation(FVector2D(WindowRect.Left, WindowRect.Top), WindowRect.GetSize(), RootWindow->IsWindowMaximized());
		RootWindowLocation.SaveToIni();
	}

	// Save the visual state of the editor before we even
	// ask whether we can shut down.
	TSharedRef<FGlobalTabmanager> GlobalTabManager = FGlobalTabmanager::Get();
	if (FUnrealEdMisc::Get().IsSavingLayoutOnClosedAllowed())
	{
		GlobalTabManager->SaveAllVisualState();
	}
	else
	{
		GConfig->EmptySection(TEXT("EditorLayouts"), *GEditorLayoutIni);
	}

	// Clear the callback for destructionfrom the main tab; otherwise it will re-enter this shutdown function.
	if (MainTabPtr.IsValid())
	{
		MainTabPtr.Pin()->SetOnTabClosed(SDockTab::FOnTabClosedCallback());
	}

	// Inform the AssetEditorManager that the editor is exiting so that it may save open assets
	// and report usage stats
	FAssetEditorManager::Get().OnExit();

	if (RootWindow.IsValid())
	{
		RootWindow->SetRequestDestroyWindowOverride(FRequestDestroyWindowOverride());
		RootWindow->RequestDestroyWindow();
	}

	// Save out any config settings for the editor so they don't get lost
	GEditor->SaveConfig();
	GLevelEditorModeTools().SaveConfig();

	// Delete user settings, if requested
	if (FUnrealEdMisc::Get().IsDeletePreferences())
	{
		IFileManager::Get().Delete(*GEditorPerProjectIni);
	}

	// Take a screenshot of this project for the project browser
	if (FApp::HasGameName())
	{
		const FString ExistingBaseFilename = FString(FApp::GetGameName()) + TEXT(".png");
		const FString ExistingScreenshotFilename = FPaths::Combine(*FPaths::GameDir(), *ExistingBaseFilename);

		// If there is already a screenshot, no need to take an auto screenshot
		if (!FPaths::FileExists(ExistingScreenshotFilename))
		{
			const FString ScreenShotFilename = FPaths::Combine(*FPaths::GameSavedDir(), TEXT("AutoScreenshot.png"));
			FViewport* Viewport = GEditor->GetActiveViewport();
			if (Viewport)
			{
				UThumbnailManager::CaptureProjectThumbnail(Viewport, ScreenShotFilename, false);
			}
		}
	}

	// Shut down the editor
	// NOTE: We can't close the editor from within this stack frame as it will cause various DLLs
	//       (such as MainFrame) to become unloaded out from underneath the code pointer.  We'll shut down
	//       as soon as it's safe to do so.
	// Note this is the only place in slate that should be calling QUIT_EDITOR
	GEngine->DeferredCommands.Add(TEXT("QUIT_EDITOR"));
}
void FSceneViewport::ResizeFrame(uint32 NewSizeX, uint32 NewSizeY, EWindowMode::Type NewWindowMode, int32 InPosX, int32 InPosY)
{
	// Resizing the window directly is only supported in the game
	if( FApp::IsGame() && NewSizeX > 0 && NewSizeY > 0 )
	{		
		FWidgetPath WidgetPath;
		TSharedPtr<SWindow> WindowToResize = FSlateApplication::Get().FindWidgetWindow( ViewportWidget.Pin().ToSharedRef(), WidgetPath );

		if( WindowToResize.IsValid() )
		{
			int32 CVarValue = GetBoundFullScreenModeCVar();
			EWindowMode::Type DesiredWindowMode = GetWindowModeType(NewWindowMode);
			
			// Avoid resizing if nothing changes.
			bool bNeedsResize = SizeX != NewSizeX || SizeY != NewSizeY || NewWindowMode != DesiredWindowMode || DesiredWindowMode != WindowToResize->GetWindowMode();

			if (bNeedsResize)
			{
				if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDEnabled())
				{
					// Resize & move only if moving to a fullscreen mode
					if (NewWindowMode != EWindowMode::Windowed)
					{
						FSlateRect PreFullScreenRect = WindowToResize->GetRectInScreen();

						IHeadMountedDisplay::MonitorInfo MonitorInfo;
						if (GEngine->HMDDevice->GetHMDMonitorInfo(MonitorInfo))
						{
							NewSizeX = MonitorInfo.ResolutionX;
							NewSizeY = MonitorInfo.ResolutionY;
							if (GEngine->HMDDevice->IsFullScreenAllowed())
							{
								WindowToResize->ReshapeWindow(FVector2D(MonitorInfo.DesktopX, MonitorInfo.DesktopY), FVector2D(MonitorInfo.ResolutionX, MonitorInfo.ResolutionY));
							}
							else
							{
								WindowToResize->Resize(FVector2D(MonitorInfo.ResolutionX, MonitorInfo.ResolutionY));
								DesiredWindowMode = EWindowMode::WindowedMirror;
							}
						}

						GEngine->HMDDevice->PushPreFullScreenRect(PreFullScreenRect);
					}
				}

				// Toggle fullscreen and resize
				WindowToResize->SetWindowMode(DesiredWindowMode);

				if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDEnabled())
				{
					if (NewWindowMode == EWindowMode::Windowed)
					{
						FSlateRect PreFullScreenRect;
						GEngine->HMDDevice->PopPreFullScreenRect(PreFullScreenRect);
						if (PreFullScreenRect.GetSize().X > 0 && PreFullScreenRect.GetSize().Y > 0 && GEngine->HMDDevice->IsFullScreenAllowed())
						{
							NewSizeX = PreFullScreenRect.GetSize().X;
							NewSizeY = PreFullScreenRect.GetSize().Y;
							WindowToResize->MoveWindowTo (FVector2D(PreFullScreenRect.Left, PreFullScreenRect.Top));
						}
					}

					if (NewWindowMode != WindowMode)
					{
						// Only notify the HMD if we've actually changed modes
						GEngine->HMDDevice->OnScreenModeChange(NewWindowMode);
					}
				}

				LockMouseToViewport(!CurrentReplyState.ShouldReleaseMouseLock());

				int32 NewWindowSizeX = NewSizeX;
				int32 NewWindowSizeY = NewSizeY;

				WindowToResize->Resize( FVector2D(NewWindowSizeX, NewWindowSizeY) );

				ResizeViewport(NewWindowSizeX, NewWindowSizeY, NewWindowMode, InPosX, InPosY);
			}
			UCanvas::UpdateAllCanvasSafeZoneData();
		}		
	}
}
void FSceneViewport::ResizeFrame(uint32 NewSizeX, uint32 NewSizeY, EWindowMode::Type NewWindowMode, int32 InPosX, int32 InPosY)
{
	// Resizing the window directly is only supported in the game
	if( FApp::IsGame() && NewSizeX > 0 && NewSizeY > 0 )
	{		
		FWidgetPath WidgetPath;
		TSharedPtr<SWindow> WindowToResize = FSlateApplication::Get().FindWidgetWindow( ViewportWidget.Pin().ToSharedRef(), WidgetPath );

		if( WindowToResize.IsValid() )
		{
			EWindowMode::Type DesiredWindowMode = GetWindowModeType(NewWindowMode);

			// If we're going into windowed fullscreen mode, we always want the window to fill the entire screen.
			// When we calculate the scene view, we'll check the fullscreen mode and configure the screen percentage
			// scaling so we actual render to the resolution we've been asked for.
			if (DesiredWindowMode == EWindowMode::WindowedFullscreen)
			{
				FDisplayMetrics DisplayMetrics;
				FSlateApplication::Get().GetInitialDisplayMetrics(DisplayMetrics);
				NewSizeX = DisplayMetrics.PrimaryDisplayWidth;;
				NewSizeY = DisplayMetrics.PrimaryDisplayHeight;;
			}

			uint32 ViewportSizeX = NewSizeX;
			uint32 ViewportSizeY = NewSizeY;

			if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDConnected())
			{
				WindowToResize->SetViewportSizeDrivenByWindow(true);
				// Resize & move only if moving to a fullscreen mode
				if (NewWindowMode != EWindowMode::Windowed)
				{
					IHeadMountedDisplay::MonitorInfo MonitorInfo;
					if (GEngine->HMDDevice->GetHMDMonitorInfo(MonitorInfo))
					{
						ViewportSizeX = MonitorInfo.ResolutionX;
						ViewportSizeY = MonitorInfo.ResolutionY;
						if (GEngine->HMDDevice->IsFullscreenAllowed())
						{
							NewSizeX = MonitorInfo.ResolutionX;
							NewSizeY = MonitorInfo.ResolutionY;
						}
						else
						{
							if (MonitorInfo.WindowSizeX != 0 && MonitorInfo.WindowSizeY != 0)
							{
								NewSizeX = MonitorInfo.WindowSizeX;
								NewSizeY = MonitorInfo.WindowSizeY;
							}
							NewWindowMode = DesiredWindowMode = EWindowMode::WindowedMirror;
							WindowToResize->SetIndependentViewportSize(FVector2D(ViewportSizeX, ViewportSizeY));
						}
					}
				}
			}

			// Avoid resizing if nothing changes.
			bool bNeedsResize = SizeX != ViewportSizeX || SizeY != ViewportSizeY || NewWindowMode != DesiredWindowMode || DesiredWindowMode != WindowToResize->GetWindowMode();

			if (bNeedsResize)
			{
				if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDConnected())
				{
					// Resize & move only if moving to a fullscreen mode
					if (NewWindowMode != EWindowMode::Windowed)
					{
						FSlateRect PreFullScreenRect = WindowToResize->GetRectInScreen();

						IHeadMountedDisplay::MonitorInfo MonitorInfo;
						if (GEngine->HMDDevice->GetHMDMonitorInfo(MonitorInfo))
						{
							if (GEngine->HMDDevice->IsFullscreenAllowed())
							{
								WindowToResize->ReshapeWindow(FVector2D(MonitorInfo.DesktopX, MonitorInfo.DesktopY), FVector2D(MonitorInfo.ResolutionX, MonitorInfo.ResolutionY));
							}
						}

						GEngine->HMDDevice->PushPreFullScreenRect(PreFullScreenRect);
					}
				}

				// Toggle fullscreen and resize
				WindowToResize->SetWindowMode(DesiredWindowMode);

				if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHMDEnabled())
				{
					if (NewWindowMode == EWindowMode::Windowed)
					{
						FSlateRect PreFullScreenRect;
						GEngine->HMDDevice->PopPreFullScreenRect(PreFullScreenRect);
						if (PreFullScreenRect.GetSize().X > 0 && PreFullScreenRect.GetSize().Y > 0 && GEngine->HMDDevice->IsFullscreenAllowed())
						{
							NewSizeX = PreFullScreenRect.GetSize().X;
							NewSizeY = PreFullScreenRect.GetSize().Y;
							WindowToResize->MoveWindowTo(FVector2D(PreFullScreenRect.Left, PreFullScreenRect.Top));
						}
						ViewportSizeX = NewSizeX;
						ViewportSizeY = NewSizeY;
						WindowToResize->SetViewportSizeDrivenByWindow(true);
					}

					if (NewWindowMode != WindowMode)
					{
						// Only notify the HMD if we've actually changed modes
						GEngine->HMDDevice->OnScreenModeChange(NewWindowMode);
					}
				}

				LockMouseToViewport(!CurrentReplyState.ShouldReleaseMouseLock());

				WindowToResize->Resize(FVector2D(NewSizeX, NewSizeY));

				ResizeViewport(ViewportSizeX, ViewportSizeY, NewWindowMode, InPosX, InPosY);
			}
			UCanvas::UpdateAllCanvasSafeZoneData();
		}		
	}
}
int32 SProgressBar::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const
{
	// Used to track the layer ID we will return.
	int32 RetLayerId = LayerId;

	bool bEnabled = ShouldBeEnabled( bParentEnabled );
	const ESlateDrawEffect::Type DrawEffects = bEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect;
	
	const FSlateBrush* CurrentFillImage = GetFillImage();
	
	const FLinearColor FillColorAndOpacitySRGB(InWidgetStyle.GetColorAndOpacityTint() * FillColorAndOpacity.Get().GetColor(InWidgetStyle) * CurrentFillImage->GetTint(InWidgetStyle));
	const FLinearColor ColorAndOpacitySRGB = InWidgetStyle.GetColorAndOpacityTint();

	TOptional<float> ProgressFraction = Percent.Get();	

	// Paint inside the border only. 
	// Pre-snap the clipping rect to try and reduce common jitter, since the padding is typically only a single pixel.
	FSlateRect SnappedClippingRect = FSlateRect(FMath::RoundToInt(MyClippingRect.Left), FMath::RoundToInt(MyClippingRect.Top), FMath::RoundToInt(MyClippingRect.Right), FMath::RoundToInt(MyClippingRect.Bottom));
	const FSlateRect ForegroundClippingRect = SnappedClippingRect.InsetBy(FMargin(BorderPadding.Get().X, BorderPadding.Get().Y));
	
	const FSlateBrush* CurrentBackgroundImage = GetBackgroundImage();

	FSlateDrawElement::MakeBox(
		OutDrawElements,
		RetLayerId++,
		AllottedGeometry.ToPaintGeometry(),
		CurrentBackgroundImage,
		SnappedClippingRect,
		DrawEffects,
		InWidgetStyle.GetColorAndOpacityTint() * CurrentBackgroundImage->GetTint( InWidgetStyle )
	);	
	
	if( ProgressFraction.IsSet() )
	{
		const float ClampedFraction = FMath::Clamp(ProgressFraction.GetValue(), 0.0f, 1.0f);

		switch (BarFillType)
		{
			case EProgressBarFillType::RightToLeft:
			{
				FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale);
				ClippedAllotedGeometry.Left = ClippedAllotedGeometry.Right - ClippedAllotedGeometry.GetSize().X * ClampedFraction;

				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D::ZeroVector,
						FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry),
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
			case EProgressBarFillType::FillFromCenter:
			{
				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D( (AllottedGeometry.Size.X * 0.5f) - ((AllottedGeometry.Size.X * ( ClampedFraction ))*0.5), 0.0f),
						FVector2D( AllottedGeometry.Size.X * ( ClampedFraction ) , AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect,
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
			case EProgressBarFillType::TopToBottom:
			{
				FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale);
				ClippedAllotedGeometry.Bottom = ClippedAllotedGeometry.Top + ClippedAllotedGeometry.GetSize().Y * ClampedFraction;

				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D::ZeroVector,
						FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry),
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
			case EProgressBarFillType::BottomToTop:
			{
				FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale);
				ClippedAllotedGeometry.Top = ClippedAllotedGeometry.Bottom - ClippedAllotedGeometry.GetSize().Y * ClampedFraction;

				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D::ZeroVector,
						FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry),
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
			case EProgressBarFillType::LeftToRight:
			default:
			{
				FSlateRect ClippedAllotedGeometry = FSlateRect(AllottedGeometry.AbsolutePosition, AllottedGeometry.AbsolutePosition + AllottedGeometry.Size * AllottedGeometry.Scale);
				ClippedAllotedGeometry.Right = ClippedAllotedGeometry.Left + ClippedAllotedGeometry.GetSize().X * ClampedFraction;

				// Draw Fill
				FSlateDrawElement::MakeBox(
					OutDrawElements,
					RetLayerId++,
					AllottedGeometry.ToPaintGeometry(
						FVector2D::ZeroVector,
						FVector2D( AllottedGeometry.Size.X, AllottedGeometry.Size.Y )),
					CurrentFillImage,
					ForegroundClippingRect.IntersectionWith(ClippedAllotedGeometry),
					DrawEffects,
					FillColorAndOpacitySRGB
					);
				break;
			}
		}
	}
	else
	{
		const FSlateBrush* CurrentMarqueeImage = GetMarqueeImage();
		
		// Draw Marquee
		const float MarqueeAnimOffset = CurrentMarqueeImage->ImageSize.X * MarqueeOffset;
		const float MarqueeImageSize = CurrentMarqueeImage->ImageSize.X;

		FSlateDrawElement::MakeBox(
			OutDrawElements,
			RetLayerId++,
			AllottedGeometry.ToPaintGeometry(
				FVector2D( MarqueeAnimOffset - MarqueeImageSize, 0.0f ),
				FVector2D( AllottedGeometry.Size.X + MarqueeImageSize, AllottedGeometry.Size.Y )),
			CurrentMarqueeImage,
			ForegroundClippingRect,
			DrawEffects,
			ColorAndOpacitySRGB
			);

	}

	return RetLayerId - 1;
}
void FSlateRemoteServer::ProcessTouchMessage( const FSlateRemoteServerMessage& Message )
{
	// @todo This should be some global value or something in slate??
	static FVector2D LastTouchPositions[EKeys::NUM_TOUCH_KEYS];
					
	if (Message.Handle < EKeys::NUM_TOUCH_KEYS)
	{
		FSlateApplication& SlateApplication = FSlateApplication::Get();

		// convert from 0..1 to window coordinates to screen coordinates
		// @todo: Put this into a function in SlateApplication
		if (SlateApplication.GetActiveTopLevelWindow().IsValid())
		{
			FVector2D ScreenPosition;

			// The remote is interested in finding the game viewport for the user and mapping the input in to it
			TSharedPtr<SViewport> GameViewport = SlateApplication.GetGameViewport();
			if (GameViewport.IsValid())
			{
				FWidgetPath WidgetPath;

				WidgetPath = GameViewportWidgetPath.ToWidgetPath();
						
				if (WidgetPath.Widgets.Num() == 0 || WidgetPath.Widgets.Last().Widget != GameViewport)
				{
					SlateApplication.FindPathToWidget(GameViewport.ToSharedRef(), WidgetPath);
					GameViewportWidgetPath = WidgetPath;
				}

				const FGeometry& GameViewportGeometry = WidgetPath.Widgets.Last().Geometry;
				ScreenPosition = GameViewportGeometry.LocalToAbsolute(FVector2D(Message.Data[0], Message.Data[1]) * GameViewportGeometry.Size);
			}
			else
			{
				const FSlateRect WindowScreenRect = SlateApplication.GetActiveTopLevelWindow()->GetRectInScreen();
				const FVector2D WindowPosition = WindowScreenRect.GetSize() * FVector2D(Message.Data[0], Message.Data[1]);
				ScreenPosition = FVector2D(WindowScreenRect.Left, WindowScreenRect.Top) + WindowPosition;
			}

			// for up/down messages, we need to let the cursor go in the same location
			// (mouse up with a delta confuses things)
			if (Message.DataType == DT_TouchBegan || Message.DataType == DT_TouchEnded)
			{
				LastTouchPositions[Message.Handle] = ScreenPosition;
			}

			// create the event struct
			FPointerEvent Event(0, Message.Handle, ScreenPosition, LastTouchPositions[Message.Handle], Message.DataType != DT_TouchEnded);
			LastTouchPositions[Message.Handle] = ScreenPosition;

			// send input to handler
			if (Message.DataType == DT_TouchBegan)
			{
				SlateApplication.ProcessTouchStartedEvent(nullptr, Event);
			}
			else if (Message.DataType == DT_TouchEnded)
			{
				SlateApplication.ProcessTouchEndedEvent(Event);
			}
			else
			{
				SlateApplication.ProcessTouchMovedEvent(Event);
			}
		}
	}
	else
	{
		//checkf(Message.Handle < ARRAY_COUNT(LastTouchPositions), TEXT("Received handle %d, but it's too big for our array"), Message.Handle);
	}
}