mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-28 12:07:48 -06:00
Merge remote-tracking branch 'origin/main' into ui/shape-group-elided-contents
# Conflicts: # docs/ui-parity.md
This commit is contained in:
+8
-3
@@ -303,7 +303,9 @@ build real projects through these interfaces; they are worked examples of everyt
|
||||
The CLI also renders an exported template directly:
|
||||
`effectcraft-cli render --template lt.ectemplate --values values.json --out 'title_[#####].png'`.
|
||||
`values.json` is an object such as `{"Title":"John Smith","Bar Color":"#00c080","Bar Opacity":50}`;
|
||||
names follow `essential.set`, including its case-insensitive matching. Values override one
|
||||
names follow `essential.set`, including its case-insensitive matching. A Media Replacement
|
||||
control takes a footage file path (`{"Clip":"/in/clipB.mp4"}`, or `{"path": …}`), which is
|
||||
imported and set as the control's `item`. Values override one
|
||||
imported instance; the template file and its source controls keep their defaults. Omit
|
||||
`--values` to render those defaults, or use the same options with `render-frame` for a PNG.
|
||||
Values must fit in 1 MiB. Invalid JSON, unknown controls and invalid values fail before rendering.
|
||||
@@ -540,8 +542,10 @@ Fonts: `text.fonts` (MCP `list_fonts`) lists every family a text layer can use,
|
||||
styles, origin (`bundled`, `system`, `user`), `variable` (it has variation axes) and own-language name
|
||||
(`{"query":"gothic"}` filters by name, `{"variable":true}` keeps only variable fonts, like the font
|
||||
menu's Variable Fonts filter; `{"rescan":true}` first picks up fonts installed since launch). Pass a listed `family` and
|
||||
one of its `styles` to `layer.setText {"font", "style"}`; `text.fontFeatures` says which OpenType
|
||||
options a font draws with its own glyphs.
|
||||
one of its `styles` to `layer.setText {"font", "style"}`. A variable font's named instances (`Light` …
|
||||
`Black`) are styles of its family; a style or an instance's PostScript name (`"font": "Figtree-Black"`)
|
||||
sets the instance's axis values, and `variations` set on the text override them axis by axis.
|
||||
`text.fontFeatures` says which OpenType options a font draws with its own glyphs.
|
||||
A tool with its own font library can hand it over without installing it: folders listed in
|
||||
`EFFECTCRAFT_FONT_DIRS` (a path list, `:`-separated, `;` on Windows) are scanned like the system font folders.
|
||||
On Linux and the BSDs the system font folders are `/usr/share/fonts`, `/usr/local/share/fonts`,
|
||||
@@ -663,6 +667,7 @@ effectcraft-cli render-frame main.ecproj --time 1 --max-side 640 --out f.png --j
|
||||
effectcraft-cli exec layer.newNull --bridge 9877 # same commands, against the live app
|
||||
effectcraft-cli exec file.exportLottie '{"comp":"Main","path":"main.json","includeExpressions":true}' main.ecproj --json
|
||||
effectcraft-cli exec file.importLottie '{"path":"anim.json"}' main.ecproj --save
|
||||
effectcraft-cli render main.ecproj --comp Main --out main.mov --format prores --progress # progress lines on stderr for a program that reads them
|
||||
```
|
||||
|
||||
Scripts written against After Effects' documented scripting API run with `script`:
|
||||
|
||||
@@ -107,6 +107,9 @@ vectors, positions and IDs are never the picture. EXtractoR reads every other la
|
||||
|
||||
## Replacing and reloading
|
||||
|
||||
Importing a layered file as a composition refreshes the decoded sources used by its layers,
|
||||
including files overwritten at the same path and byte size.
|
||||
|
||||
- **File ▸ Replace Footage ▸ File…** (Ctrl+H) points the item at another file. Pick a numbered
|
||||
file to replace it with that file's whole sequence (`file.replaceFootage {"path": …,
|
||||
"sequence": false}` for one frame).
|
||||
|
||||
+16
-2
@@ -1,6 +1,6 @@
|
||||
# Where EffectCraft falls short
|
||||
|
||||
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-12 · **Change:** minor (issue, PR and catalog references gap 21: percentage guides and effect colour labels in; earlier change: re-audited against `upstream/main` 470ea7a3; ranked gap list from the 10 October re-measure otherwise unchanged) · **Target:** Adobe After Effects 2026 (26.5.0.89)
|
||||
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-13 · **Change:** minor (path-editing layer bounds, #1220; issue, PR and catalog references gap 21: percentage guides and effect colour labels in; earlier change: re-audited against `upstream/main` 470ea7a3; ranked gap list from the 10 October re-measure otherwise unchanged) · **Target:** Adobe After Effects 2026 (26.5.0.89)
|
||||
|
||||
An honest assessment of how far EffectCraft is from being a real replacement for After Effects,
|
||||
and the work that closes the gap. This document is meant for contributors and agents choosing
|
||||
@@ -64,7 +64,7 @@ are grouped by area; the issue tracker has the rest.
|
||||
| 5 | **Playback and scrubbing feel** | #595 stutter on cached frames (partly addressed: nearest-first RAM preview prefetch, cache bars at 1/3 resolution), #304, #504 / #335 audio late or crackling, #586 puppet lag (maintainers asked for details); #329 slow scrubbing (#784) and #554 closed | Preview is where motion designers spend their day | 25–50 h | G5 · [hardware-parity.md](hardware-parity.md) |
|
||||
| 6 | **Linux and Windows interaction bugs** | Open: #488 rename arrows (hardening landed, reporter asked for details), #492 anchor drag, #268 file drops on Wayland (winit), #613 Direct3D 12 compositor. Now closed: #491, #493, #467, #320, #302, #596 | Many reports come from Linux; some Windows GPUs fail to start the compositor | 25–45 h | G2 · [ui-parity.md](ui-parity.md) |
|
||||
| 7 | **Animation presets: 54 against 621** | After Effects ships 621 `.ffx` presets (Behaviors, Backgrounds, Shapes, Synthetics, Text, Transitions…); we ship 54 original presets (8 text-animator; 23 Transitions: wipes, clock and fan reveals, blinds, dissolves, card flips, CC wipes, fades, #757; 23 Backgrounds: drifting gradients, fog, cloud and smoke, plasma and magma, cells, hexagons, scrolling grids and checks, pulse rings, bokeh, light sweep, #1096, driven by expressions so they keep moving, not seamless loops) and read only our `.ecpreset`. Missing: Behaviors, Shapes, Synthetics, Image and more Text | Presets are how many designers start; tutorials assume them | 15–35 h (original presets; `.ffx` reading is out of clean-room scope) | G8 · [effects-parity.md](effects-parity.md) |
|
||||
| 8 | **Mask and shape bugs** | Open: #1004 mask vertex multi-select, #999 auto-pan, #1042 / #1033 vertex nodes under the bounding box, #932 Convert to Bezier Path, #959 / #960 shape group toggles and operators. Now closed: #510, #513, #527, #509, #303, #553 | Masks are core compositing | 10–20 h | G2 · [target-app-parity.md](target-app-parity.md) |
|
||||
| 8 | **Mask and shape bugs** | Open: #1004 mask vertex multi-select, #999 auto-pan, #1042 / #1033 vertex nodes under the bounding box, #959 / #960 shape group toggles and operators. Now closed: #510, #513, #527, #509, #303, #553, #932 (Convert To Bezier Path on a shape layer's parametric path) | Masks are core compositing | 10–20 h | G2 · [target-app-parity.md](target-app-parity.md) |
|
||||
| 9 | **Effect behaviour bugs** | #580, #463 Curl Noise, #369 Motion Tile output size, #943 Turbulent Displace Evolution, #473 Cryptomatte selection (quoted names with commas fixed, 3b7f1ace; UI and GPU time open), #474 multi-layer EXR (decode shared, faffad3a; f16 storage and cache sizing open). Closed: #526, #514, #533–#536 | Each one breaks a look someone built | 10–20 h | G1/G2 · [effects-parity.md](effects-parity.md) |
|
||||
| 10 | **Colour pipeline differences** | #340 ProRes 4444 tagged bt709 but sRGB-encoded (open); ACES 2.0 / OCIO 2.5 configs (26.5) missing; now closed: #494 32-bpc blend modes, #495 and #750 Working Gamma 2.4, #546 / #547 viewer colour | Wrong colour in delivery is a client-visible failure | 15–30 h | G1 · [file-format-parity.md](file-format-parity.md) |
|
||||
| 11 | **Text rendering and layout** | Open: #453 CJK text in comps, #316 paragraph alignment inverted (maintainers' tests show Left/Right correct; asked for a project), #417 soft at Fit (mostly fixed by #444), #550 toolbar font options. Closed: #483, #583 | Text is in almost every motion graphic | 10–20 h | G2 · [ui-parity.md](ui-parity.md) |
|
||||
@@ -114,6 +114,9 @@ The most important missing piece: it turns every other estimate here into a meas
|
||||
- Run the headless snapshot and control-channel checks on Linux (X11 and Wayland) and Windows, not
|
||||
only macOS. Interactions that only fail with real input (docking drags, viewer pan, drag-and-drop
|
||||
import, inline rename) need scripted input tests.
|
||||
- Path editing (#1220): selected shape and mask paths suppress the layer transform box while
|
||||
their points are edited. `ui_viewer` regressions cover Pen-family tools, Selection vertex
|
||||
dragging and undo, restoration of layer controls, and layers without visible paths.
|
||||
- Regression evidence for [#66](https://github.com/storytold/effectcraft/issues/66): scripted
|
||||
pointer tests in `ui_viewer` and `ui_text_edit`, checked headlessly on Linux, cover viewer clicks,
|
||||
marquee selection and text picking when layers are hidden or excluded by solo. They also check
|
||||
@@ -146,6 +149,15 @@ The most important missing piece: it turns every other estimate here into a meas
|
||||
tests, checked headlessly on Windows, drag a selected Gradient Fill's start and end points in
|
||||
the Composition viewer: one undo step, the layer stays, a point inside a moved and scaled group
|
||||
converts to the group's space, and the handles show only for a selected gradient.
|
||||
- Regression evidence for [#1011](https://github.com/storytold/effectcraft/issues/1011): the
|
||||
`ui_text_range_handles` input tests, checked headlessly on macOS, drag a text Range Selector's
|
||||
End bar in the Composition viewer: one undo step, Start and the layer stay, and on an animated
|
||||
End a keyframe at the current time. The bars show only for a selected selector or a selected
|
||||
animator (or a property in it), with the Selection tool and layer controls on. Unit tests in
|
||||
`text` place the bars on unit boundaries (words and Characters Excluding Spaces skip spaces,
|
||||
inside a ligature, on the second line, right to left) and invert them; `render` covers the
|
||||
value a drag writes (less the Offset, whole units in Index). Not done: dragging Offset, bars on
|
||||
vertical text and on text on a path.
|
||||
- Regression evidence for the toolbar's gradient swatches (#612, reported on Discord): the
|
||||
`ui_toolbar_gradient` input tests, checked headlessly on Windows, click a Linear Fill swatch and
|
||||
a Radial Stroke swatch on a selected shape layer and get the Gradient Editor on its Gradient Fill
|
||||
@@ -323,6 +335,8 @@ Issues #41–#47 (all from the Linux AppImage 0.1.1, 5 October): panning the vie
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-16 | minor | Gap 8: #932 closed (Convert To Bezier Path converts a shape layer's parametric path, not only mask RotoBezier) |
|
||||
| 2026-10-13 | patch | G2: layer bounds no longer compete with editable shape/mask path points (#1220) |
|
||||
| 2026-10-12 | minor | Audited against `upstream/main` 470ea7a3: open-issue count and crash list, closed issues removed from rows 1, 3, 5, 6, 8–12, 15–17, 22–24, G8 and G9 (#759 `#include`), localization catalogs recounted (≈ 12% to ≈ 18%); rows 7, 14 and 21 left to open PRs #1102, #792 and #1098 |
|
||||
| 2026-10-10 | minor | Alpha gate checked: no alpha blockers |
|
||||
| 2026-10-12 | minor | Gap 21: percentage guides and effect colour labels added (#1095) |
|
||||
|
||||
+13
-6
@@ -103,17 +103,24 @@ name in your Scripts folders takes their place.
|
||||
|
||||
### Ease Presets (`extensions/scriptui-panels/Ease Presets.jsx`)
|
||||
|
||||
Window ▸ Ease Presets.jsx: easing curves kept by name and applied to pairs of neighbouring
|
||||
selected keyframes (#254; it was a core panel in v0.6.0). A curve is the out side of a segment's
|
||||
Window ▸ Ease Presets.jsx: easing curves kept by name and applied to the sides of selected
|
||||
keyframes (#254; it was a core panel in v0.6.0). A curve is the out side of a segment's
|
||||
first key and the in side of its second, in the Keyframe Velocity dialog's terms: influence in
|
||||
percent, and speed relative to the segment's average speed (1 = as fast as a straight line, 0 = at
|
||||
rest), so one curve fits any duration and change of value.
|
||||
|
||||
* Click a preset to apply it to every pair of neighbouring selected keyframes of each selected
|
||||
property, in one undo step (per dimension, and along the motion path for spatial properties;
|
||||
the keys' other sides keep playing as they did). The keys stay selected, so you can try another.
|
||||
* Click a preset to apply it to the selected keyframes of each selected property, in one undo
|
||||
step. **Ease** chooses the sides (#1329): **In** eases each key's incoming side with the curve's
|
||||
in side, **Out** its outgoing side with the curve's out side, **In-Out** (the default) both. A
|
||||
side is eased when it has a neighbouring keyframe, selected or not (the neighbour doesn't
|
||||
change), with its speeds scaled to the segment on that side: per dimension, and along the
|
||||
motion path for spatial properties. So a single keyframe works, a selected pair gets the whole
|
||||
curve, and the first and last keys ease the side that has a segment. The side not eased keeps
|
||||
playing as it did (a Hold stays a Hold). Roving keyframes are skipped, and the status says how
|
||||
many: they pass speed straight through, so an ease on one wouldn't play (turn off Roving to
|
||||
ease it). The keys stay selected, so you can try another.
|
||||
* The drawing shows the working curve; type its numbers (Out % and Speed, In % and Speed) and
|
||||
click Apply, or click From Keys to read the curve between the first selected pair.
|
||||
click Apply, or click From Keys to read the curve between the first selected pair of neighbouring keys.
|
||||
* Save keeps the working curve under the typed name (replacing a preset of that name); Rename
|
||||
and Delete act on the selected preset of your own. The twelve built-in presets can't change.
|
||||
* User presets are kept with `app.settings` (section `Ease Presets`, key `userPresets`, in
|
||||
|
||||
@@ -15,7 +15,7 @@ our own scripts; no real-world script library has been run against both apps.
|
||||
| Feature | After Effects 2026 | EffectCraft | Status | Evidence / gap |
|
||||
|---|---|---|---|---|
|
||||
| Expression language | JavaScript engine (default) and Legacy ExtendScript | JavaScript (boa) with legacy array maths (`value + [10, 0]`) | good | `crates/expr` tests; no separate Legacy ExtendScript engine mode |
|
||||
| Expression object model | `thisComp`, `thisLayer`, `wiggle`, `loopOut`, `valueAtTime`, `sampleImage`, `footage()`, text style API… | Same members, from the reference | good | `crates/expr/src/tests.rs`; behaviour of edge cases unmeasured (G1) |
|
||||
| Expression object model | `thisComp`, `thisLayer`, `wiggle`, `loopOut`, `valueAtTime`, `sampleImage`, `footage()`, text style API… | Same members, from the reference, including `propertyGroup(countUp)` and a group's `propertyIndex` for name-independent rigs (#1619) | good | `crates/expr/src/tests.rs`, `tests/property_group.rs`; behaviour of edge cases unmeasured (G1) |
|
||||
| Expression editing | Inline field, error bar, pick whip, Expression Language menu, external editors | Inline field that grows, error bar, pick whips (property and value), language menu | partial | External editor support (#364) |
|
||||
| Expression performance | Cached, multi-frame | Per-thread boa contexts | unknown | No benchmark |
|
||||
| Scripting object model | `app`, `Project`, items, layers, properties, keys, eases, render queue, `TextDocument`, `Shape`, markers, `File`/`Folder`, `Socket`, `app.settings` | Same classes, edits run through undoable engine commands; match names table; layers, groups and properties are callable (`layer("Effects")(1)` is `.property(...)`) | good | `crates/script` tests (≈ 10 test files) |
|
||||
@@ -42,5 +42,6 @@ performance benchmark 4–8 h.
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-16 | minor | Expression object model row names `propertyGroup()` and a group's `propertyIndex` (#1619) |
|
||||
| 2026-10-12 | minor | Estimate no longer counts `#include` / `#target` (#759, `tests_include.rs`); the table row was already current |
|
||||
| 2026-10-10 | major | First expressions and scripting checklist |
|
||||
|
||||
@@ -746,6 +746,9 @@ them: scripts, ScriptUI panels, effect plug-ins, with a guide to writing a panel
|
||||
way and move them however slowly they are dragged; the same Shift / Ctrl / Ctrl+Alt clicks.
|
||||
- **Paste** (M5.13): keys copied from several layers paste onto as many layers in order; Paste
|
||||
Reversed Keyframes follows Paste's rules (stretch, target property, Hold-only properties).
|
||||
A Mask Path or shape Path (its value or a key) pasted onto Position becomes a motion path: a
|
||||
key per vertex with the path's tangents, over 2 s from the CTI, the inner keys roving, the
|
||||
vertices pasted as they are (layer space, as in After Effects) (#1425).
|
||||
- **J / K and Info** (M5.14): J / K also stop at the work area; the Info panel shows a selected
|
||||
key's property, time and value.
|
||||
|
||||
|
||||
@@ -68,6 +68,15 @@ instructions retired; `/usr/bin/time -v` on Linux gives max RSS and CPU; elsewhe
|
||||
It prints a table and appends one JSON line per run to `target/bench/results.jsonl` (git rev,
|
||||
date, load average, scenario, settings, metrics); `--compare OLD.jsonl` prints the % change against
|
||||
the latest matching runs there, `--compare OLD --with NEW` compares two files without rendering.
|
||||
`--repeat N` runs every scenario N times; with N > 1, one `"kind": "summary"` line per key follows
|
||||
the runs. Its `metrics` are the medians of the successful runs (byte and instruction counts
|
||||
rounded), `summary` holds `runs`, `failed` and median/p90/min/max per metric (p90 is the nearest
|
||||
rank, so it equals the max for N < 10), and its other fields (`date`, `load`, ...) are those of the
|
||||
key's last run; scripts that average runs should skip `kind: summary` lines. One failed run marks
|
||||
the summary failed. Comparisons use the latest line per key, so a key is a median only if its
|
||||
summary is the latest line (a later single run, or a batch that aborted before its summaries,
|
||||
leaves a raw run latest). The table labels each side `median of N` or `1 run` and warns when they
|
||||
differ; `--fail-over` refuses such keys.
|
||||
The table notes the 1-minute load average: on a busy machine wall time is noise, so compare
|
||||
peak memory and instructions retired, and rerun when the load differs a lot.
|
||||
|
||||
|
||||
+8
-1
@@ -1,6 +1,6 @@
|
||||
# UI parity
|
||||
|
||||
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-18 · **Change:** minor (closed issue references re-audited against `upstream/main` 470ea7a3) · **Target:** Adobe After Effects 2026
|
||||
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-18 · **Change:** minor (shape group Contents row elided; path-editing layer bounds #1220; closed issue references re-audited against `upstream/main` 470ea7a3) · **Target:** Adobe After Effects 2026
|
||||
|
||||
How closely EffectCraft's interaction matches After Effects: tools, handles, snapping, nudging,
|
||||
modifier keys, shortcuts, drag behaviour, numeric entry, panels, context menus and feel. Evidence
|
||||
@@ -33,6 +33,12 @@ feel and platform differences, and the 26.x interface changes are not in yet.
|
||||
| Accessibility | AccessKit enabled; focus labels tested; Project panel keyboard navigation and accessible names (#776) | 20% | No screen-reader pass or keyboard-navigation audit of the other panels; no contrast check |
|
||||
| UI scale | Settings ▸ Appearance ▸ UI Scale 75–200% | beyond | After Effects follows the system's scaling (#284) |
|
||||
|
||||
Path editing (#1220): the Composition viewer suppresses a selected layer’s transform box while
|
||||
using a Pen-family tool on a visible path, or while selecting its vertices with the Selection
|
||||
tool. Path points, Bézier handles and the path’s free-transform controls remain available.
|
||||
Layer transform tools and ordinary layer selection restore the box. Headless `ui_viewer` tests
|
||||
cover shape paths and masks, corner-vertex dragging and undo, and layers without visible paths.
|
||||
|
||||
## Estimate
|
||||
|
||||
**≈ 60–120 h**: the open interaction issues above (25–45 h, about 0.2–0.5 h each with a scripted
|
||||
@@ -45,6 +51,7 @@ Effects running; most of the rest parallelises.
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-18 | minor | A shape group's inner Contents (After Effects' elided Vectors group) draws no row: the group's path, fill/stroke and Transform list directly under the group |
|
||||
| 2026-10-13 | patch | Layer bounds are suppressed during path-point editing (#1220); shape/mask interaction regressions |
|
||||
| 2026-10-12 | minor | Closed issues (#302, #320, #491, #511, #553 and others) marked as closed instead of open; panels in their own windows (#486) |
|
||||
| 2026-10-12 | minor | Percentage guides and effect colour labels (26.5) added; rows updated |
|
||||
| 2026-10-10 | major | First UI parity checklist |
|
||||
|
||||
+12
-4
@@ -156,8 +156,9 @@ of the project:
|
||||
|
||||
Frames without effects that the WebGPU compositor can finish alone still render on the page
|
||||
(they stay on the GPU, no readback); everything else (frames with effects, 3D runs, the Software
|
||||
Only renderer, WebGL2) goes to the workers. If no worker is usable, frames render on the page's
|
||||
thread as before. `effectcraft.info().frameWorkers` reports `{workers, alive, busy, rendered,
|
||||
Only renderer, WebGL2) goes to the workers. If no worker is usable (one that failed to start, or
|
||||
one the browser refused to create, as in a sandboxed iframe), frames render on the page's thread
|
||||
as before. `effectcraft.info().frameWorkers` reports `{workers, alive, busy, rendered,
|
||||
failed, lastMs, syncs, syncBytes, gpu, gpuFrames, lastPasses, diskHits}` (`gpu`: each worker's
|
||||
adapter, `{cpu: why}` without one, `null` until it reported).
|
||||
|
||||
@@ -425,14 +426,21 @@ node apps/effectcraft-web/tests/smoke.mjs --url http://127.0.0.1:8765/ --out tar
|
||||
|
||||
`apps/effectcraft-web/tests/workers.mjs` checks the job-worker plumbing (`js/host.js`,
|
||||
`web/worker.js`) under Node with a fake `Worker`, without a build: a replaced file is sent to a
|
||||
reused worker again even at the same size, and a worker that fails to start fails its job and is
|
||||
terminated (`node apps/effectcraft-web/tests/workers.mjs`).
|
||||
reused worker again even at the same size, a worker that fails to start fails its job and is
|
||||
terminated, and a `new Worker` that throws (a sandboxed iframe) fails the job and reports the
|
||||
frame worker dead instead of stopping startup (`node apps/effectcraft-web/tests/workers.mjs`).
|
||||
|
||||
`apps/effectcraft-web/tests/page.mjs` checks page-side helpers of `js/host.js` the same way with
|
||||
a fake DOM: a picked file that can't be read is reported while the others are added, and the
|
||||
device-lost notice saves, flushes before reloading and reports a failed flush
|
||||
(`node apps/effectcraft-web/tests/page.mjs`).
|
||||
|
||||
`apps/effectcraft-web/tests/storage.mjs` checks the IndexedDB storage backend of `js/host.js`
|
||||
with a fake IndexedDB: a put or delete resolves only once its transaction has committed, and one
|
||||
whose transaction aborts after its request succeeded (or whose request fails or throws) rejects
|
||||
and leaves the stored entry as it was, so the flush keeps it for a retry (#1242)
|
||||
(`node apps/effectcraft-web/tests/storage.mjs`).
|
||||
|
||||
It also checks the M13.10 paths: viewer frames rendered in frame workers while scrubbing with the
|
||||
CPU renderer (project synced as diffs, event-loop gaps under 400 ms), a `wait: true` render that
|
||||
replies when done while the page keeps running, and the Media Browser over browser storage; and
|
||||
|
||||
Reference in New Issue
Block a user