How to get the screen location of a viewport?

I’ve been using a different method in PIE vs Standalone builds for a long time. It’s nice that I can finally unify them under one method (Slate’s TakeScreenshot). The problem I previously faced was this method would capture the whole editor window, and I only wanted the viewport. I could get the viewport size, but was struggling to get its position.

Thanks for adding ViewportToVirtualDesktopPixel, and I’m glad I found it mentioned in this thread. From there I could subtract the window position and have the viewport position in the window. Odd that UE makes this so hard, but at least this function makes it possible! I hadn’t found it before because it’s undocumented and I wasn’t sure if it was meant for use, or something internal.

For anyone who needs help with the conversion, here’s some code. Viewport is the PIE viewport. Size is that viewport’s size.

			TSharedPtr<SWindow> ViewportWindow = Viewport->FindWindow();
			TSharedRef<SWindow> Window = ViewportWindow ? ViewportWindow.ToSharedRef() : GEngine->GameViewport->GetWindow().ToSharedRef();

			// Attempt to only screenshot the PIE viewport section
			FVector2D UpperLeftInViewport(0, 0);
			FIntPoint UpperLeftInDesktop = Viewport->ViewportToVirtualDesktopPixel(UpperLeftInViewport);
			// Need to subtract window position to go from pos in desktop to pos in window.
			auto WindowRect = Window->GetRectInScreen();
			FIntPoint UpperLeftInWindow = UpperLeftInDesktop - FIntPoint(WindowRect.GetTopLeft2f().X, WindowRect.GetTopLeft2f().Y);
			FIntRect InnerWidgetArea(UpperLeftInWindow.X, UpperLeftInWindow.Y, UpperLeftInWindow.X + Size.X, UpperLeftInWindow.Y + Size.Y);
			bSuccess = FSlateApplication::Get().TakeScreenshot(Window, InnerWidgetArea, Bitmap, ScreenshotSize);

Context: For those curious, yes there are other ways to take a screenshot or get a texture from a camera (such as having a camera render target), but I have specific needs that those other methods kept failing at. I need to get the screenshot immediately, not waiting for a render frame to pass. I need the buffer in memory, not saved to a file. And most importantly, I need to have the screenshot perfectly match the current viewport’s buffer, so I can put the texture over the screen while I do other stuff, then fade it away in whatever cinematic way we like. Any discretion in postprocessing or colors etc is jarring when we display the texture over what the player was seeing, so directly fetching the viewport buffer or calling Slate’s TakeScreenshot (which does the same thing) is ideal.

Cheers, all!