Repository navigation
Add offscreen editor-window capture automation (#114) - #123
Merged
Merged
Conversation
The #114 capture-automation slice needs a Unity-side capture path: macOS TCC denies `screencapture` to the Unity editor process, so window rasterization must never read the desktop. EditorSurfaceCapture hosts a window as a popup, settles its UI Toolkit panel layout, renders the panel into an offscreen linear RenderTexture through three repaint/render cycles, and reads back only that target; the panel's ValidateLayout/Repaint/Render are internal with no public equivalent, so the reflective invocation fails closed if a Unity upgrade renames them. Every graphics global is restored and every texture destroyed, including on failure. EditMode tests prove the mechanism end to end: the real DataVisualizer window captures to a valid non-blank PNG; a deterministic surface captures twice with byte-identical output; guards fail closed on null window and empty paths; -nographics editors skip. Red check: with the render passes suppressed both content assertions fail on a blank frame (Expected: greater than 1, But was: 1), so the tests catch a broken render pipeline rather than vacuous PNGs. Two capture-specific rules came out of an interaction with SplitterWidthPersistenceTests: the capture host must be a dedicated window type nothing else looks up by name (a popup-hosted LayoutTestWindow was reused as their dock anchor, clamping the pane to its 320 minimum), and CloseWindow must DestroyImmediate because EditorWindow.Close does not reliably unregister popup-hosted windows. The real-window test also snapshots and restores the window EditorPrefs keys its lifecycle can touch. Validation: full EditMode 311/311 (305 prior + 6 new), PlayMode 15/15 on the Unity 6000.4.6f1 host; lint ladder green; npm pack payload unchanged at 172 files (Tests are not shipped). Refs #114.
Eli Pinkerton (wallstop)
added a commit
that referenced
this pull request
Oct 10, 2026
DISCLOSURE: LLM-GENERATED TEXT **Why:** The 300-rendered-character entry cap was guidance only, so nothing failed when an entry drifted past it. **What:** - Add a lint that measures `[Unreleased]` entries as rendered text. - Exclude issue references and inline link targets from the count. - Fail closed on a missing or duplicated `[Unreleased]` section. - Wire the lint into the ladder, pre-commit, and `llm-lint` CI. Fixes #159 ## Type of Change - [x] New feature (non-breaking change that adds functionality) ## Checklist - [x] I have added tests that prove my fix is effective or my feature works - [x] I have updated the documentation accordingly - [ ] I have updated the [CHANGELOG](../CHANGELOG.md) for user-facing changes - [x] My changes do not introduce breaking changes, or breaking changes are documented <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Adds CI/pre-commit tooling and tests only; no runtime or release artifact behavior changes beyond blocking over-long changelog drafts. > > **Overview** > Turns the existing **300 rendered-character** cap for `CHANGELOG.md` `[Unreleased]` entries from documentation into an enforced check via new `scripts/lint-changelog-length.js`. > > The linter measures **rendered** text (joined wraps, stripped emphasis/code markers) and **does not count** issue references (`#123`, `(#123)`) or inline link URLs; it only scans `[Unreleased]`, and **fails closed** if that section is missing or duplicated. It is hooked into **pre-commit** (on `CHANGELOG.md`), **`llm-lint` CI**, `npm run lint:changelog-length`, and `lint:llm:full`, with **PowerShell self-tests** covering boundary cases and exclusions. Agent docs (`ship-changes`, `.llm/context.md`) now point contributors at `npm run lint:changelog-length`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5f3e450. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Tests-assembly offscreen editor-window capture path so docs imagery (#114) can be regenerated without OS screen capture, which macOS TCC denies to the Unity editor process.
Behavior
EditorSurfaceCapturepopup-hosts a window, settles its panel layout, renders into an offscreen linear RenderTexture through three repaint/render cycles, and writes a 24-bit PNG; no desktop pixels are ever read, and internal panel methods fail closed if a Unity upgrade renames them.-nographicseditors skip. Red check: suppressed render passes fail the non-blank assertions (But was: 1), proving the tests detect a broken pipeline.EditorSurfaceCaptureHostWindowtype (a popup-hostedLayoutTestWindowwas reused as SplitterWidthPersistenceTests' dock anchor, clamping the pane to 320) and destroy-firstCloseWindow(Close()does not reliably unregister popup-hosted windows).Validation
npm packpayload unchanged at 172 files (Tests are not shipped).Risk / Rollback
Refs #114. Also this run: #121 verified on
mainand closed on the issue with host evidence (issue #121 comment).Note
Low Risk
Changes are confined to the Tests assembly with no production or shipped-package surface; the main fragility is reflection on internal UI Toolkit panel APIs, which fails loudly on Unity upgrades.
Overview
Adds Tests-only infrastructure to screenshot Unity
EditorWindowUI Toolkit surfaces without OS screen capture (workaround for macOS TCC blockingscreencaptureon the editor), targeting documentation image regeneration (#114).EditorSurfaceCapturepopup-hosts the window, iterates layout until stable, then drives the panel through reflectiveValidateLayout/Repaint/Renderinto an offscreen linearRenderTexture, encodes a PNG, and restores graphics state and textures on success or failure. It refuses-nographicseditors and missing/invalid inputs instead of writing blank images, and reportsDistinctColorCountso tests can detect empty renders.Supporting types include a dedicated
EditorSurfaceCaptureHostWindow(avoids reuse with other tests’ window lookups) andDestroyImmediate-basedCloseWindowteardown. EditMode tests cover fail-closed guards, byte-identical deterministic captures, and a real DataVisualizer window producing a valid non-blank PNG, with EditorPrefs snapshot/restore around the integration test.Reviewed by Cursor Bugbot for commit 2c847a6. Bugbot is set up for automated code reviews on this repo. Configure here.