Commit Graph
17 Commits
Author SHA1 Message Date
BFlat 7099fe0bae Merge pull request #1874 from vangel76/rfx-masks-shapes
Mask feather, Repeater opacity and Trim Paths on rectangles render as in After Effects
2026-10-30 01:21:47 +07:00
dotCooCoo 32f058ea05 Merge main into feat/wiggle-paths-spatial-phase 2026-10-28 05:39:33 -07:00
Dylan M. Taylor 5d71dce7fc Refactor render for strict Clippy checks 2026-10-28 06:09:21 +00:00
dotCooCoo 8ebacda419 Shapes: Wiggle Paths has Spatial Phase, which slides its wiggle along the path
Wiggle Paths had Size, Detail, Points, Wiggles/Second, Correlation,
Temporal Phase and Random Seed, but no Spatial Phase, which After
Effects lists among its properties (ADBE Vector Spatial Phase). Spatial
Phase now moves each point's own displacement along its subpath: 360
degrees is once around, and a fraction of a point is interpolated
between neighbors. At 0 degrees a path draws as before.

A project saved without the property gets it at 0 degrees, after
Temporal Phase, when it opens. Scripts can read and set every Wiggle
Paths property by its match name.
2026-10-25 16:06:28 -07:00
vangel76andClaude Opus 5.5 710ffd9f7e Shapes: Repeater copy opacity steps 1 / Copies toward End Opacity, as After Effects
After Effects gives Repeater copy i the opacity Start + (End - Start) * i / Copies,
so the last copy stops one step short of End Opacity. EffectCraft reached End
Opacity at the last copy (i / (Copies - 1)). Measured in AE 2026 (case 709: 3
copies, End Opacity 40): copies at 100 / 80 / 60 % (EffectCraft 100 / 70 / 40);
the overlap of the two copies 92 % (EffectCraft 82 %). Now within 2/255 at the
sampled pixels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:33:44 +02:00
Brandon Thomas de7c8d6dd6 Merge pull request #1271 2026-10-18 09:35:33 -04:00
wixar172andClaude Opus 5.5 9846c7255d Shapes: a stroke's buffer is padded by the miter limit only where it has miter joins
draw_bounds padded every stroke by width × miter limit / 2 on each side, joins or
not. A straight 1080 px wide wipe used as a track matte became a 4326×6366 layer
buffer (~440 MB as RGBA f32), made anew every frame while its trim animates, then
cached on the CPU and uploaded to the GPU. With 12 frames exported in parallel a
16 GB Mac ran out of memory and froze.

Now the miter limit applies only to miter-joined paths with a join (two or more
segments, or closed); square caps reach √2 half widths, other strokes one; Taper
and Wave keep the widest padding. Rendered pixels are unchanged.

A full-res frame of the affected ad: 1.7 GB → 0.7 GB peak.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:20:02 +03:00
Vikram Bhaskaran 48738093b5 Shapes: Merge Paths keeps paint that belongs to a group above it (#1174)
A Merge Paths item appended to a shape layer's Contents cleared every draw
collected so far, including fills and strokes inside groups above it, so
the layer's shapes vanished from the render. AE's rule is per group: only
paint items in the merge's own group above it are dropped. Draws now
record which contents level created them; the merge drops only its own
group's paint, and the group-bubbled draws keep rendering.

Adds a regression test (Merge Shapes and Add modes) that renders nothing
without the fix.
2026-10-14 00:02:12 +11:00
vangel76andClaude Opus 5.5 fb5a5e9ac0 #315: Front / Bevel / Side / Back Color for extruded shapes and text
Problem: In Advanced 3D, an extruded shape or text layer was one mesh in
its paint colour. After Effects colours the front, bevel, side and back
of an extrusion separately (shape Contents ▸ Add ▸ Front/Bevel/Side/Back,
text Animate ▸ Front/Bevel/Side/Back), and EffectCraft had none of it.

Fix: The extruder can split its mesh by surface (front cap, bevel rings,
walls, back cap). Shape layers get Front / Bevel / Side / Back contents
items (layer.addShapeItem kinds frontColor…backColor, one item per
group, colouring every paint of the group and its nested groups; the
innermost wins). Text animators get Front / Bevel / Side / Back Color,
blended over the character's fill or stroke by the selection. Paints
with a surface colour render as one mesh per surface. Menus, the
Contents Add: pop-up and the menu translations list them. The other
surface material properties (Ambient, Diffuse, Specular, Metal,
Reflection, ...) remain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:05:36 +02:00
Claude 86d47dc3fe Snapping and Align: shape layers meet at their visual edges, with no gap (#352)
Cause: render::content_bounds (used by snapping's targets and source, Align,
Distribute, the viewer's bounding box and handles) took shape layers' bounds
from draw_bounds, the rasteriser's safety rectangle: 1 px of anti-aliasing
padding around fills and width x miter limit / 2 + 1 around strokes. Two
squares snapped edge to edge therefore stayed 2 px apart, or much more with
strokes.

Fix: shapes::content_bounds uses visual bounds, as After Effects' layer bounds
do: the path bounds plus half the stroke width (through the draw's group
scale), with no anti-aliasing or miter padding. Rendering keeps draw_bounds.

Tests: render shape_content_bounds_are_the_visual_edges (a 100 x 100
rectangle is exactly +-50, +-55 with a 10 px stroke); engine
shape_layers_align_by_their_visual_edges (widths 100 / 110, Align Left puts
both edges exactly at 0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
(cherry picked from commit bfd0abd7437ad1d38652e3aef51f9ba5dea9100b)
2026-10-10 19:48:25 +00:00
Brandon ThomasandClaude Opus 5.5 07da394ccb M13.8: Advanced 3D iris depth of field, collapsed precomps, extruded strokes
Depth of field in Advanced 3D comps uses the camera's iris (Fast Rectangle, Triangle to
Decagon, rotation, roundness, aspect, diffraction fringe) and highlight gain/threshold/
saturation through the Classic 3D bokeh kernel. Collapsed precomps in an Advanced 3D comp
add their nested layers as real geometry (meshes, extrusions, cards) lit by the parent;
2D collapsed precomps draw nested 3D layers with the parent's renderer. Text and shape
strokes extrude as bevelled meshes stacked in paint order (model extrude_stacked).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 07:47:25 -04:00
Brandon ThomasandClaude Opus 5.5 bbaee1fa0f M13.5: stroke taper/wave/multi-dashes, radial gradient highlight, variable-width mask feather, adaptive motion-blur samples
Shapes (SHP-2): Stroke Taper (pixels/percent start/end length, width, ease) and
Wave (amount, pixels/cycles, wavelength, phase) rendered as a variable-width
outline; Dash 2/Gap 2/Dash 3/Gap 3 (shape.dashes.add/remove, timeline +/-
buttons); radial gradient Highlight Length/Angle as a focal gradient.
Masks (MSK-1): mask feather points on the Mask Path (mask.featherPoint.*,
Mask Feather tool add/drag), per-point signed radius and tension, rendered
from the signed distance to the path; carried through vertex edits.
Motion blur (LYR-10): Adaptive Sample Limit comp setting; 2D layers take one
sample per pixel of shutter travel between Samples Per Frame and the limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:22:53 -04:00
Brandon ThomasandClaude Opus 5.5 dec091e575 M7.5: advanced 3D renderer
Advanced 3D comps render their 3D runs as one scene of world-space triangles: model and
primitive layers (meshes, skinning, animation clips by layer time), extruded text/shape
layers, and textured cards for every other layer with their Material Options. Shading is
physically based in linear light: Cook-Torrance GGX + Lambert for parallel/spot/point lights
(AE falloff and cone), ambient lights, image-based light from an Environment light's layer
(equirectangular; cosine irradiance map + roughness mip chain + split-sum BRDF fit), and
PCF shadow maps (spot/parallel/point cube faces). 2x2 SSAA, depth of field as a gather blur
by circle of confusion, back to the working encoding.

The software rasteriser (depth buffer, top-left rule, perspective-correct, opaque visibility
then sorted transparent blending) is the reference and CI path; effectcraft-gpu implements
Accelerator::raster_3d with a wgpu render pipeline (advanced3d.wgsl) and matches it within
tolerance. Environment layers are hidden from both renderers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 21:27:59 -04:00
Brandon ThomasandClaude Opus 5.5 468dc13cfe M0.13: viewer snapping, rulers, channels, snapshots, ROI
Composition viewer interaction parity with After Effects:
- Snapping (View > Snapping, the Tools bar checkbox, Cmd/Ctrl inverts while
  dragging): layer edges, centres and anchor points, mask and shape-path
  vertices, comp edges/centre, guides (Snap to Guides) and grid (Snap to
  Grid), with highlighted target box / line / cross feedback. Pure maths in
  engine::viewer (nearest target within tolerance, priority ties).
- Rulers (Cmd+R) with live pointer markers and a draggable zero point;
  guides dragged out of the rulers, moved in the viewer, dragged off to
  remove (view.moveGuide / view.removeGuide), lock respected; proportional
  grid.
- Show Channel (RGB/Red/Green/Blue/Alpha/RGB Straight, Colorize), exposure
  (+/- stops in linear light, reset), Take Snapshot (Shift+F5) with a stored
  render and Show Snapshot (F5 held / button held), Fast Previews (Off,
  Adaptive Resolution, Draft, Fast Draft, Wireframe), Resolution > Custom.
- Region of interest: drawn in the viewer; RenderOpts.roi renders only that
  rectangle (crop of the full render, tested), Crop Comp to ROI uses it.
- Bottom bar in AE 2026 order ("136.1 %", "(Full)").
- Shape Pen (SHP-1): Pen on a shape layer / nothing selected draws Shape n
  groups (Path 1, Stroke 1, Fill 1) via shape.newPath; the G slot cycles
  Add / Delete / Convert Vertex and Mask Feather; mask.* vertex commands
  work on shape paths; mask.insertVertex / mask.convertVertex; marquee
  vertex selection, Alt-drag/click converts, double-click free transform
  box (path.freeTransform on masks and shape paths).
- Motion paths (ANM-3): keyframe dots and spatial tangent handles, dragging
  keys (keys.set) and tangents (keys.setSpatialTangents), parented layers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 10:16:05 -04:00
Brandon ThomasandClaude Opus 5.5 0ec4605a32 M0.6: content bounds helpers for viewer handles
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:32:21 -04:00
Brandon ThomasandClaude Opus 5.5 ba2fa1bddf M6.2: shape path operators (round corners, offset, twist, zig zag, wiggle, merge paths, gradient stroke)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:26:28 -04:00
Brandon ThomasandClaude Opus 5.5 808cd490cd M0.1–M0.7: workspace, time/geom/color/keyframe/project/raster/path/text/effects/render crates
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:05:20 -04:00