#if UNITY_6000_7_OR_NEWER
using System.IO;
using System.Linq;
using Unity.Pipeline.Commands;
using Unity.Pipeline.Runtime.Commands;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace Unity.Pipeline.Editor.Commands
{
///
/// Captures a UI Toolkit from an to a PNG
/// and returns it base64-encoded (and writes it to disk). The element is located by a USS-like
/// selector within the window's .
///
/// Selection, capture, and encoding are shared with the runtime command via
/// ; this command only resolves the target window.
///
public static class CaptureEditorElementCommand
{
[CliCommand("capture_editor_element",
"Capture a UI Toolkit VisualElement (by selector) from an EditorWindow to a PNG; returns path + base64.",
MainThreadRequired = true)]
public static CaptureElementResponse CaptureEditorElement(
[CliArg("window", "EditorWindow type name (e.g. InspectorWindow) or window title to capture from.", Required = true)] string window = "",
[CliArg("selector", "Element selector: '#name', '.class', a type name (e.g. Button), descendant (space) / child ('>') chains, optional pseudo-states (:checked,:hover,:focus,:active,:enabled,:disabled,:not(...)).", Required = true)] string selector = "",
[CliArg("output", "Output PNG path (absolute, or relative to the project root). Defaults to a timestamped file under /Temp/pipeline-screenshots/.")] string output = "")
{
if (string.IsNullOrWhiteSpace(window))
return CaptureElementResponse.Fail("A 'window' (EditorWindow type name or title) is required.");
if (string.IsNullOrWhiteSpace(selector))
return CaptureElementResponse.Fail("A 'selector' is required.");
var target = ResolveWindow(window);
if (target == null)
return CaptureElementResponse.Fail(
$"No open EditorWindow matched '{window}' (by type name or title). Open the window first.");
var root = target.rootVisualElement;
if (root == null)
return CaptureElementResponse.Fail($"EditorWindow '{window}' has no rootVisualElement.");
var element = VisualElementCaptureSupport.ResolveElement(root, selector);
if (element == null)
return CaptureElementResponse.Fail(
$"No element matched selector '{selector}' in window '{window}'.");
var projectRoot = Path.GetDirectoryName(Application.dataPath);
var defaultDir = Path.Combine(projectRoot, "Temp", "pipeline-screenshots");
return VisualElementCaptureSupport.CaptureAndRespond(
element, selector, $"window:{window}", output,
relativeBaseDir: projectRoot, defaultDir: defaultDir, prefix: "element");
}
///
/// Find an open EditorWindow whose runtime type name or title matches .
/// Uses Resources.FindObjectsOfTypeAll so hidden/utility windows are included too, but
/// prefers a match whose root is actually attached to a panel — FindObjectsOfTypeAll can
/// also return stale/backup window instances whose rootVisualElement has no panel (and
/// therefore cannot be captured).
///
static EditorWindow ResolveWindow(string window)
{
var windows = Resources.FindObjectsOfTypeAll();
bool Matches(EditorWindow w) =>
w.GetType().Name == window ||
(w.titleContent != null && w.titleContent.text == window);
return windows.FirstOrDefault(w => Matches(w)
&& w.rootVisualElement != null && w.rootVisualElement.panel != null)
?? windows.FirstOrDefault(Matches);
}
}
}
#endif