Repository navigation
feat(renderer): interactive view capture() → Blob (DD-030 D1) - #418
Merged
Merged
Conversation
Add capture(opts?) that returns the currently displayed view as an image Blob, for user-selected thumbnails, large-file fallback, and screenshots. Available on GcodePreviewControls.capture (all 4 adapters inherit it; the Web Component adds an imperative method) and ModelViewer.capture; implemented on InteractiveStage and delegated by ToolpathRenderer. Mechanism = render-to-target: render the current scene + active camera into an off-screen WebGLRenderTarget at the requested size and read it back, so it never flips the interactive preserveDrawingBuffer default nor disturbs the live view, and supports an arbitrary output size + independent/transparent background. The library returns the Blob and never triggers a download (caller owns the pixels, same contract as renderStill). Honest: capture() rejects with a typed CaptureUnsupportedError (E_CAPTURE_UNSUPPORTED) when the renderer cannot render-to-target (2D renderer, stub GL / no WebGL) or the stage is disposed/context-lost. Purely additive (new optional method on the renderer contract). Final increment of the DD-030 batch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4 tasks done
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.
DD-030 increment 3/3 — interactive
capture()(completes the batch)Final DD-030 increment (bed ✅ → per-plate ✅ → capture). Gates AnyBridge's built-and-waiting PR #1371.
What
capture(opts?)returns the currently displayed view as an imageBlob— user-selected thumbnails, large-file fallback, screenshots.opts = { width?, height?, format?, quality?, background? }(all optional; defaults match the live view).Surfaces (all inherit one implementation):
GcodePreviewControls.capture()→ the Vue / React / Svelte adapters inherit it via the existingcontrolspassthrough (zero adapter code); the Web Component adds an imperativecapture().ModelViewer.capture()on the model-viewer handle.InteractiveStage(impl) +ToolpathRenderer(delegate);PreviewRenderergains an optionalcapture?.Mechanism — render-to-target
Renders the current scene + active camera into an off-screen
WebGLRenderTargetat the requested size and reads it back — so it never flips the interactivepreserveDrawingBufferdefault (no per-frame tax), never disturbs the live view, and supports an arbitrary output size + independent/transparent background. Reuses the headless still path's "single render, then read pixels" recipe; frames the thumbnail at its own aspect (no distortion); repaints the live view afterward. Returns theBlob; never triggers a download (caller owns the pixels, same contract asrenderStill).Honest & additive
Rejects with a typed
CaptureUnsupportedError(code: 'E_CAPTURE_UNSUPPORTED') when the renderer can't render-to-target (the 2D renderer, a stub GL / no WebGL) or the stage is disposed / context-lost. Purely additive — a new optional method on the renderer contract; no existing signature changed.Tests
The GL-free halves are unit-tested (
flipRowsRGBA,resolveCaptureSize), and the unsupported path is verified throughToolpathRenderer.capture()with a stub GL (rejectsE_CAPTURE_UNSUPPORTED). The full pixel path (render-target readback + canvas encode) is browser-only — consistent with this package's stub-GL testing convention — and is validated end-to-end by the gated consumer integration (AnyBridge PR #1371). Full suites green: renderer-three 156, model-renderer 61, core 35; all 6 built packages compile.This completes DD-030. Additive → the whole batch rides one lockstep minor (v0.18.0).
🤖 Generated with Claude Code