Commit Graph
865 Commits
Author SHA1 Message Date
vangel76andClaude Opus 5.5 617b0a578d Exposure: After Effects parameter ranges
All twelve sliders (Master, Red, Green, Blue) take After Effects'
ranges: Exposure valid -100..100, slider -4..4, 2 decimals (was -20..20,
slider -5..5); Offset -2..2, slider -0.5..0.5, 4 decimals (unchanged);
Gamma Correction valid and slider 0.1..10, 2 decimals (was 0.01..9.99,
slider 0.1..3).

Every value inside the old Exposure and Offset ranges stays valid. Saved
values are not clamped on load, so a gamma below 0.1 from an older
project or a Photoshop import (0.01..9.99) is kept and still renders
(the renderer's 0.01 floor is unchanged); only new edits clamp to 0.1.
Test of the ranges and of an old gamma surviving the load refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:14:26 +02:00
vangel76andClaude Opus 5.5 c7060e2d75 Exposure: gamma 2.2 linear-light conversion, as After Effects
With Bypass Linear Light Conversion off, Exposure decoded and re-encoded
with the piecewise sRGB curve. After Effects 2026 renders (sRGB working
space, 32 bpc) of Offset 0.0005 / 0.002 / 0.02 / 0.1 on black measure
8 / 15 / 43 / 90, which a pure 2.2 power predicts (8.06 / 15.13 / 43.08 /
89.54) and the sRGB curve does not (1.65 / 6.59 / 38.68 / 89.04).

The effect now uses its own 2.2 power curve on the CPU and in the GPU
kernel; the shared colour functions and other effects are unchanged. As
before, the conversion applies whatever the working space, also a
linearised one. Negative values go through both curves mirrored (input
was clamped at 0 before), so defaults are an identity for 32-bpc values
and a negative Offset darkens past black without NaN.

New test against the AE values; existing Exposure tests still hold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:14:26 +02:00
vangel76andClaude Opus 5.5 70c1349cbc Black & White: Tint keeps the gray's luminosity, as After Effects
After Effects tints Black & White's gray like a Color blend: the tint colour's
hue and saturation at the gray's luminosity (weights 0.3 / 0.59 / 0.11, channels
outside 0..1 pulled back toward the gray). EffectCraft used the gray as HSL
lightness. Measured in AE 2026, Tint Color [1, 0.5, 0]: a red solid at Reds 10
(case 717) AE (43, 21, 0), EffectCraft was (51, 26, 0), now (43, 21, 0); a
yellow solid at the default sliders (gray 0.6, case 825) AE (255, 129, 2), now
(255, 129, 3); white stays white. The six sliders already matched AE on eight
colours (cases 816, 817). CPU and GPU.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:14:21 +02:00
vangel76andClaude Opus 5.5 960f41d50b Tritone: Rec. 601 luminance, as After Effects
After Effects' Tritone weighs the working-space values with Rec. 601 (0.299,
0.587, 0.114), as its Tint does; EffectCraft used Rec. 709. Case 718 (red solid,
Highlights [1,1,0.8], Midtones [0.6,0.2,0.2], Shadows [0,0,0.3], Blend 25):
AE (132, 23, 46), EffectCraft was (113, 16, 49), now (132, 23, 46). On a grey
ramp (case 815) the shadows / midtones / highlights mapping already matched and
still does within 1/255. CPU and GPU (fx_color op 4).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:13:41 +02:00
vangel76andClaude Opus 5.5 fb16d5573e Tint: Rec. 601 luminance weights, as After Effects
After Effects 2026 (sRGB working space, not linearised) maps red, green,
blue and 50% grey solids at Tint's defaults to 76, 150, 29 and 128/255:
Rec. 601 weights on the working-space values, not Rec. 709. CPU and GPU
kernel changed; tests pin the four greys within 1/255.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:12:50 +02:00
Camille Moine 4f3fa4d0fb docs: the Timeline row controls act on the selection (#1849)
One bullet in the Timeline section of docs/agents.md and a note on the
ui-parity Timeline row, next to the other multi-selection fixes.
2026-10-19 09:55:40 +02:00
Matej Kozlovský 76098665b0 Cryptomatte: effect.pickCryptomatte picks the ID under a point into the Selection (#473)
Engine part of viewer picking: replace / add / remove the top-coverage ID at a
layer-space point in one undo step, at the time the Selection was read. The
aux channels come from the render's own path (Renderer::layer_aux, shared with
the effect host; footage at its source time, 3D precomps) through a renderer
set up like Session::render (expressions, render prefs, layer cache). An
optional scale snaps the point to the pixel a preview at that resolution
samples. New effects::crypto_select quotes names and falls back to <hex> for
unnamed, wildcard-looking or ambiguous names. effect.cryptomatteAt is the
read-only hover query.
2026-10-19 06:10:27 +02:00
vangel76andClaude Sonnet 5.5 4f3851206a Merge upstream/main into feat-gap25-a11y-audit
Resolve conflicts in the Effects & Presets panel, the arrow-key nudge and the
docs; update two a11y tests to the prefs-based favourites.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 02:06:49 +02:00
vangel76andClaude Sonnet 5.5 24612b0eaf Merge upstream/main into gap-behaviors-presets
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 02:02:16 +02:00
Davit MatchakhelidzeandClaude Opus 5.5 5a069af3fd Merge i18n-improvements (main merged)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-19 02:58:18 +04:00
Davit MatchakhelidzeandClaude Opus 5.5 7d03c0a1f6 Merge main; context menus use upstream's context_item (#1308)
Upstream now translates the Timeline, Composition and Effect Controls context menus itself, so
command_label is left for the dock's tab titles and the workspace bar, on menu_catalog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-19 02:58:04 +04:00
tylerjenningsw d2ae0bd503 Merge main into enhance/avi-import 2026-10-18 12:45:36 -04:00
tylerjenningsw dd50e42486 Merge remote-tracking branch 'origin/main' into enhance/pickwhip-index-refs
# Conflicts:
#	crates/ui-egui/tests/ui_inline_edit.rs
2026-10-18 12:38:44 -04:00
Brandon Thomas a594abf4f7 Merge pull request #1652
# Conflicts:
#	docs/gaps.md
2026-10-18 09:35:51 -04:00
Brandon Thomas 043eb5a157 Merge pull request #1787 2026-10-18 09:35:35 -04:00
Brandon Thomas 692feb7925 Merge pull request #1778 2026-10-18 09:35:35 -04:00
Brandon Thomas 436f826c3d Merge pull request #1712 2026-10-18 09:35:35 -04:00
Brandon Thomas 40fe8ef969 Merge pull request #1689 2026-10-18 09:35:34 -04:00
Brandon Thomas 4d61409662 Merge pull request #1672 2026-10-18 09:35:34 -04:00
Brandon Thomas 4c196ee8e5 Merge pull request #1620 2026-10-18 09:35:34 -04:00
Brandon Thomas 65d955c32a Merge pull request #1572 2026-10-18 09:35:34 -04:00
Brandon Thomas 736c0ec4b4 Merge pull request #1430 2026-10-18 09:35:33 -04:00
Brandon Thomas 0728169fc9 Merge pull request #1384 2026-10-18 09:35:33 -04:00
Brandon Thomas b72425a28d Merge pull request #1334 2026-10-18 09:35:33 -04:00
Brandon Thomas 6648c5befe Merge pull request #1269 2026-10-18 09:35:33 -04:00
Brandon Thomas bb8dd41af1 Merge pull request #1087 2026-10-18 09:35:32 -04:00
MarekSpodBiedry c74e67ca32 Let render --template --values fill a media replacement control with a file path (#1780) 2026-10-18 13:53:15 +02:00
ArchersIntelandClaude Sonnet 5.5 c6b700fe83 feat(cli): render --progress reports frames on stderr when it is not a terminal
A terminal already gets a live `[1/1] frame 16/180 ... ~14.2s left` line while
`effectcraft-cli render` runs. A program that starts the CLI (FilmCraft runs it to
render a composition for a clip) reads stderr through a pipe, so it saw nothing
until the render ended.

`--progress` prints one line per update instead, at most four a second:

    progress <frames done> <frames total> <seconds elapsed> <seconds left, or - when unknown>

It has no effect on a terminal, which keeps its live line. Without the flag
nothing changes.

Documented in the usage text, the module header and docs/agents.md.

Tests: cargo fmt --check and cargo clippy --all-targets -D warnings pass; the
effectcraft-cli tests pass except render_out_is_relative_to_the_working_directory,
which already fails on Windows (it compares a canonicalize()d `\?\` path with the
path the CLI prints) and is unrelated to this change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 02:17:33 -05:00
Egon5000 09dad1a51f Timeline: a shape group's inner Contents draws no row, as After Effects elides it 2026-10-18 02:49:56 +02:00
tylerjenningsw 0a57bb9fc2 Docs: the AVI variants that don't import yet (#1701) 2026-10-17 14:02:18 -04:00
tylerjenningsw 84d0f56765 Docs: AVI import (#1701) 2026-10-17 11:35:05 -04:00
MarekSpodBiedry 351f2591fd Fall back to the page's thread when new Worker throws in a sandboxed iframe (#1586) 2026-10-17 07:47:33 +02:00
Matej Kozlovský d1c1e23bb9 xtask bench --repeat N: median/p90/min/max summary, compare by median
Runs every scenario N times (default 1, unchanged). Every run is still
appended to results.jsonl; with N > 1 one "kind": "summary" row per key
follows, whose metrics are the medians of the successful runs (user_s and
sys_s included, byte/instruction counts rounded) and whose summary holds
median, p90 (nearest rank, = max for N < 10), min and max. A failed run marks
the summary failed so the gate refuses it.

--compare uses the latest row per key; the table labels each side "median
of N" or "1 run" and warns when they differ, and --fail-over refuses such
keys. --repeat with --with is rejected. docs/testing.md documents the format.
2026-10-16 19:39:53 +02:00
Marco Arnulfo 9d56675da9 Text: drag a Range Selector's Start and End in the Composition viewer (#1011) 2026-10-16 18:45:11 +02:00
vangel76andClaude Sonnet 5.5 ea5bd7d171 Merge main into #1339; keep both sides of effects_presets.rs, settings.rs
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 16:16:29 +02:00
Hamza 0c39995d0f Convert a shape layer's parametric path to a bezier path (#932)
`path.convertToBezier` only cleared `roto_bezier` on mask groups, so on a shape
layer it did nothing at all: a Rectangle, Ellipse or Polystar path stayed
parametric and its vertices could not be edited or animated. In After Effects
the command replaces such a path with an editable Path 1 of the same geometry.

The geometry is not re-derived. `parametric_path` calls the same
`effectcraft_path::{rect, ellipse, polystar}` functions `render::shapes::collect`
calls, with the same defaults for a property a group doesn't carry, so the path
that comes out is the shape that was on screen; `from_kurbo` and
`build::shape_path` then make an ordinary Path 1.

Masks are unchanged: shape items take precedence when selected, and with none
selected the command falls through to the old mask behaviour. Path Direction is
carried over rather than reset, since reversing a path is a separate command,
and the new path is left selected so its vertices can be edited straight away.

The parametric properties are read at the current time and the result is a
static path: a Size or Roundness animation cannot survive becoming a vertex
list, in After Effects either. Undo restores the parametric shape.
2026-10-16 18:13:08 +05:00
Gert Pellin 0bdf9ec5e3 Merge branch 'main' into expr-property-group-1619 2026-10-16 14:28:34 +02:00
bflatastic 82784f69ea Merge main into #1640; keep both sides of docs/ui-parity.md 2026-10-16 19:04:25 +07:00
BFlat 901d54c55f Merge pull request #1594 from rahal/fix/script-host-files
fix(web): scripts can open files in browser storage; stored footage isn't reported missing (#1593)
2026-10-16 19:04:06 +07:00
BFlat fa5eff7210 Merge pull request #1332 from Themolx/null-visibility-switch
Null layers: the Video switch hides them in the Composition viewer, as in After Effects
2026-10-16 19:02:24 +07:00
BFlat e483a1c89c Merge pull request #1512 from vangel76/gap-timeline-effect-label
#1509: Timeline effect rows show the effect's colour label
2026-10-16 19:01:04 +07:00
BFlat a3b62822be Merge pull request #1331 from onlymoein/codex/fix-1303-benchmark-evidence
Reject corrupt benchmark results and incomplete regression evidence
2026-10-16 18:13:45 +07:00
BFlat 5db68bf34a Merge pull request #1302 from vbasky/fix/1194-liquify-offset
Liquify: expose Distortion Mesh Offset in Effect Controls (#1194)
2026-10-16 18:10:30 +07:00
BFlat eac13d1cf1 Merge pull request #948 from Themolx/solo-outside-active-range
Solo: exclude other layers even when the soloed layer is outside its time range
2026-10-16 18:10:06 +07:00
krinry 00c1eb54a8 #1611: layer context menu has Layer Styles
Add Layer Styles submenu to the Timeline and Composition viewer layer context menu, matching After Effects parity and the application Layer ▸ Layer Styles menu.

- Adds Layer Styles submenu between Blending Mode and Effects
- Exposes Layer Style Options..., Convert to Editable Styles, Show All, Remove All, and the 9 individual styles
- Translates Layer Styles across all 7 UI catalogs
- Adds regression test verifying submenu presence, position, and action invocation
2026-10-16 16:01:34 +05:30
bflatasticandClaude Opus 5.5 bafc7e620d Docs: parity docs list Composition - Retain Layer Sizes for PDF / Illustrator (#1536)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:05:49 +07:00
BFlat f3148ee0b1 Merge pull request #1399 from arnav-hiwarkar/feat/media-browser-copy-source-path
feat(media-browser): add Copy Source Path
2026-10-16 17:03:16 +07:00
BFlat 73d483812f Merge pull request #1402 from arnav-hiwarkar/fix/presets-menu-automation-followup
fix(presets): identify copy folder action by label
2026-10-16 17:02:54 +07:00
Gert Pellin d347a0efca Expressions: propertyGroup() and a group's propertyIndex (#1619)
The After Effects stagger idiom
  id = thisProperty.propertyGroup(2).propertyIndex;
failed with "not a callable function": the expression object model had
no propertyGroup() and property groups had no propertyIndex.

- Property.propertyGroup(countUp = 1) and PropertyGroup.propertyGroup()
  return the group countUp levels up; from a top-level group they reach
  the layer. A count below 1, not a number, or above the layer is an
  error naming propertyGroup, never a crash.
- PropertyGroup.propertyIndex: the group's 1-based index among its
  siblings (Child requests now carry it).
- One new host request (Ancestor) walks up from the node's full uid
  path, so it also works for the property being evaluated.
- Tests for the stagger expression, effect parameters, reaching the
  layer, other layers' properties and groups and out-of-range counts;
  the fuzzer seeds and tokens include the new members.
2026-10-16 05:31:49 +02:00
skylar taylor-barrickandCodex c2f790b1d9 refactor(pdf): share structure parsing through a bounded adapter
Load PDF document objects through the pinned craft-pdf parser and convert them into EffectCraft's existing drawing model with bounded traversal, recovery and retained data. Preserve generation numbers, stream limits, encrypted-document refusal and reported repairs.

Retain app-owned drawing, EPS, fonts and content/image decoding. Assert early excessive-nesting rejection without partial art, and cover tolerant arrays on native and WASM.

Validated with the22-stage local matrix and exact-head FreeBSD, Windows ARM64 and packaging checks.

Co-authored-by: Codex <noreply@openai.com>
2026-10-15 16:35:49 -06:00