#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