Created
August 3, 2023 07:02
-
-
Save markeahogan/69fc4d9722eadc20882c9aeda261fc56 to your computer and use it in GitHub Desktop.
Adds method to save the whole inspector to a screenshot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Threading.Tasks; | |
using UnityEditor; | |
using UnityEngine; | |
using UnityEngine.UIElements; | |
/// <summary> | |
/// Provides functionality for screenshotting full editor windows, and the inspector in particular | |
/// </summary> | |
public static class InspectorCapture | |
{ | |
private const int _tabsHeight = 20; | |
private const int _footer = 4; | |
/// <summary> | |
/// Takes a screenshot of the entire inspector | |
/// </summary> | |
[MenuItem("Popup Asylum/Capture Inspector")] | |
public static async void CaptureInspector() | |
{ | |
EditorWindow inspector = EditorWindow.GetWindow(typeof(Editor).Assembly.GetType("UnityEditor.InspectorWindow")); | |
await CaptureWindow(inspector); | |
} | |
/// <summary> | |
/// Captures the window and saves it as a png in the project folder | |
/// </summary> | |
/// <param name="window">window to screenshot</param> | |
/// <returns>Task completed when the process finishes</returns> | |
public static async Task CaptureWindow(EditorWindow window) | |
{ | |
var bytes = (await ScreenshotAsync(window)).EncodeToPNG(); | |
var filename = $"{window.GetType().Name}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.png"; | |
File.WriteAllBytes(Application.dataPath + $"/../{filename}", bytes); | |
} | |
/// <summary> | |
/// Scrolls the window to the top then incrementally scrolls to the bottom taking screenshots till the whole thing is captured | |
/// </summary> | |
/// <param name="window">The window to screenshot</param> | |
/// <returns>A texture containing the editor window</returns> | |
static async Task<Texture2D> ScreenshotAsync(EditorWindow window) | |
{ | |
List<Color> pixels = new List<Color>(); | |
float originalScroll = SetScroll(window); | |
var baseHeight = window.position.height - (_tabsHeight + _footer); | |
for (int i = 0; i < 64; i++) | |
{ | |
float desiredScroll = baseHeight * i; | |
float scroll = await ScrollTo(desiredScroll); | |
int offset = (int)(desiredScroll - scroll); | |
pixels.InsertRange(0, ReadWindowPixels(window, offset)); | |
if (offset > 0) | |
break; | |
} | |
SetScroll(window, originalScroll); | |
int width = (int)window.position.width; | |
int height = pixels.Count / width; | |
Texture2D texture = new Texture2D(width, height, TextureFormat.RGB24, false); | |
texture.SetPixels(pixels.ToArray()); | |
return texture; | |
// wraps scrolling and delayedCall in a Task as scrolling requires a frame to update | |
Task<float> ScrollTo(float scroll) | |
{ | |
float result = SetScroll(window, scroll); | |
var tcs = new TaskCompletionSource<float>(); | |
EditorApplication.delayCall += () => tcs.TrySetResult(result); | |
return tcs.Task; | |
} | |
} | |
/// <summary> | |
/// Captures a section of the window | |
/// </summary> | |
/// <param name="window">Window to capture</param> | |
/// <param name="offset">an optional vertical offset from the bottom</param> | |
/// <returns></returns> | |
private static Color[] ReadWindowPixels(EditorWindow window, int offset = 0) | |
{ | |
int width = (int)window.position.width; | |
int height = (int)window.position.height - (_tabsHeight + _footer + offset); | |
return UnityEditorInternal.InternalEditorUtility.ReadScreenPixel(window.position.position + new Vector2(0, _tabsHeight + offset), width, height); | |
} | |
/// <summary> | |
/// Sets the editor window's scroll, returns the resulting scroll value | |
/// </summary> | |
/// <param name="inspector">The window to scroll</param> | |
/// <param name="scroll">the y value of the scroll</param> | |
/// <returns>the value passed in clamped to the min max scroll of the window</returns> | |
private static float SetScroll(EditorWindow inspector, float scroll = -1) | |
{ | |
var scrollViewField = inspector.GetType().GetField("m_ScrollView", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); | |
var scrollView = scrollViewField.GetValue(inspector) as ScrollView; | |
if (scroll >= 0) scrollView.scrollOffset = new Vector2(0, scroll); | |
return scrollView.scrollOffset.y; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment