Commit Graph
20 Commits
Author SHA1 Message Date
FredApps ea2af8e677 Merge pull request #3228 from vangel76/shape-path-snap-2681
Viewer snapping: a point beats a line pair through it unless the pair is clearly nearer
2026-11-14 17:26:19 +01:00
FredApps c3cdaecdc6 Merge pull request #3240 from vangel76/shift-snap-axis-3229
Viewer: a Shift-constrained drag snaps only along its axis
2026-11-14 17:25:59 +01:00
arnav-hiwarkar 5b3a469181 #2817: read the selection in place and name the Closed tests for what they prove 2026-11-12 18:36:20 +05:30
arnav-hiwarkar 0ccfd669fb #2817: Closed fits short tangent lists like mask.setClosed 2026-11-12 18:24:01 +05:30
arnav-hiwarkar d7011a36b8 #2817: Closed falls back to the layer's paths when the selection names none
Selecting a non-path property (Position) or a stale selection disabled Closed, unlike
RotoBezier and the other Mask and Shape Path commands, which fall back to every mask of
the selected layers. A selected mask property (Feather, Opacity, Expansion) now selects
its mask. A selected locked mask still counts as a match, so it never falls back to its
unlocked siblings.
2026-11-12 18:22:21 +05:30
arnav-hiwarkar 36aa437d34 #2817: pin RotoBezier tangents, mixed checkmark and static paths for Closed 2026-11-12 18:20:05 +05:30
arnav-hiwarkar 37b0ea1145 Merge upstream main into fix/issue-2817-open-close-path
# Conflicts:
#	crates/engine/src/cmd/mask.rs
2026-11-12 18:14:02 +05:30
vangel76 25a6a76c47 Doc comments for the functions this PR touches 2026-11-07 19:50:42 +01:00
vangel76 714ff82fd6 Viewer: a Shift-constrained drag snaps only along its axis
A layer Move, path-vertex drag or Pan Behind drag held to one axis with
Shift snapped with the full 2D rule, so a point target (another layer's
corner or midpoint, a path vertex, the comp centre) gave the snap both of
its coordinates and pulled the dragged feature off the axis.

The new engine function viewer::snap_along snaps only the free coordinate:
a point acts as a line through it across the drag, reaching it within the
tolerance on each axis; lines along the drag are left out. A point hit
reports the point and the short line from it to where the feature landed,
so the viewer draws the alignment. The viewer's SnapQuery carries the axis
one_axis picks (drag_axis); Move, Vertices and Pan Behind pass it. snap()
itself is unchanged.

Fixes #3229
2026-11-07 15:35:14 +01:00
vangel76 d733a699fc Viewer snapping: a point beats a line pair through it unless the pair is clearly nearer (#2681)
Moving a circle so its edge point met another circle's point snapped at
200 % but missed at 100 %. A layer's point lies on its own edge line and
centre row, so a vertical and a horizontal line through it tie with it, and
the point only won that tie by 1e-9. Any other line a little nearer on one
axis (the comp's centre row, a guide) then made a pair nearer than the
point, taking x from the edge and y from that line and leaving the moved
circle off the point. At 100 % the tolerance (8 screen points) covers more
comp pixels and reaches those lines; zoomed in they were out of reach.
Before #2855 a single nearer line was enough, which is how it was reported
on 0.18.0.

snap() now lets a line pair with a line through the point beat that point
only when the pair is nearer by POINT_BIAS of the tolerance (2 of the 8
screen points at any zoom), in place of the exact tie. A pair whose lines
both miss the point gets no margin, so a guide crossing right beside a
layer's point stays reachable; two clearly nearer lines still win, as
#2855 intended.

Tests: two Ellipse-tool circles, parametric and converted to Bezier paths,
at 1x, 2x and 4x on device scales 1, 1.25 and 1.5, dropped just off the
point and nearer the comp's centre row than the circle's own row, with and
without snapping to a guide between them: the moved point lands exactly on
the other's, a single point hit (a path point for the Bezier circles). The
margin: a pair through the point only a little nearer leaves the point, a
clearly nearer one wins; a guide crossing 1 px beside a point is reached
next to the crossing.

Moving a layer snaps the feature nearest where it was grabbed, as before
(the snap handle, as in After Effects): grab the circle near its edge point
to snap that point; grabbed in the middle, its centre snaps.

Fixes #2681
2026-11-07 14:39:14 +01:00
Valentin KleinandClaude Sonnet 5.5 fdcc715829 Viewer exposure on the full float range of 32 bpc frames (#2937)
* Viewer exposure on the full float range of 32 bpc frames (#2797)

32 bpc viewer frames on the desktop are rendered without the HDR step (skip_hdr_step,
#2916) and kept as half floats in the RAM preview. A display pass on egui-wgpu's device
turns each frame into one RGBA8 texture with mips per viewer, in this order: decode,
exposure in linear light, Compand / Tone Map, encode, display colour, Show Channel,
rounding. Before, exposure was an 8-bit lookup applied after tone mapping, clamping and
the display conversion, so -2 EV could not bring values above 1.0 back.

- engine: viewer::DisplayPass describes the pass as data; its pixel() is the CPU
  fallback (no device) and the shader's reference. It replaces exposure_lut /
  display_transform. FrameEncoding records a frame's curve and the HDR step it still
  needs. 32 bpc snapshots are taken without the HDR step; snapshot_rgba8 applies it.
- ui-egui: FrameImage::CpuF16 (half crate, F16C at run time), byte accounting at 8 bytes
  a pixel in the cache and the prefetch estimates; display_gpu.rs + display_gpu.wgsl;
  main viewer, snapshot and passive viewers draw through the pass; the 8-bit image other
  panels read is made on demand with the HDR step; the Info panel shows float values.
- Half-float frames are not written to the disk cache yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Viewer display pass: f16 disk cache entries, window-device gating, review fixes

- Disk cache: half-float frame entries (format byte in the entry header, byte planes +
  LZ4); 8-bit entries keep format 0 and stay valid. 32 bpc viewer frames are written and
  read again, and the timeline's disk bar sees them. A damaged half-float entry is
  deleted.
- The display pass runs on the window's egui-wgpu device, with or without the GPU
  compositor (still building, failed, GL fallback). Its pipelines are made inside error
  scopes; a backend that rejects them gets the CPU pass instead of a blank viewer.
- A new LUT of the same size (another ICC profile, Preserve RGB, another display) runs
  the pass again.
- f32 to f16: one pass per L1-sized block, the NaN / infinity fix-up on the bits, no
  fill of the buffer (4K: 4.7 ms, as the 8-bit conversion).
- Mips of odd-sized levels include the last column / row; the snapshot's half floats
  and texture go with the snapshot; no placeholder texture ids; u64 size checks.
- Tests: LUT profiles and negative values against the shader, Bake reruns, the passive
  viewer's colour, f16 disk round trips; exact comparisons allow 1 LSB on software
  rasterizers. Docs: the display pass and the f16 disk entries in architecture.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Viewer f16 disk-cache test: temp dir removed on failure too, wait for the queued disk write

Review points: the test's directory was only removed by its last statement
(now tempfile::TempDir), and the frame is released before its disk write is
queued, so flush() could return early (now waits for the entry).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Viewer: oversized half-float frames use the CPU display pass, so exposure/HDR come before the averaging down

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Viewer: fmt and a debug assert for the half-float upload path

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Disk cache: persist_missing also writes half-float frames

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Passive viewer: oversized half-float frames take the CPU display pass instead of leaving a stale texture

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 17:37:23 +01:00
Bar BorerandClaude Opus 5.5 8a37ff6b43 Tests: trim the midpoint snap tests to what #2855 changes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 05:07:59 +02:00
Bar BorerandClaude Opus 5.5 39119ff9ce Viewer: dragged layers snap to other layers' midpoints and center lines (#2855)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 20:36:57 +02:00
arnav-hiwarkar 2b1b688557 #2817: honor combined path and shape group selections 2026-11-02 22:16:19 +05:30
arnav-hiwarkar c5bf611909 #2817: allow reopening manually drawn paths 2026-11-02 22:10:35 +05:30
Kristian Myram 2883ae9e57 #1685: discard removed property selections after undo 2026-10-30 03:27:14 +01:00
Kristian Myram 088bedff45 #1685: preserve composition selection and resolve all expression targets 2026-10-30 02:58:46 +01:00
Kristian Myram 86b357162c #1685: synchronize Polystar controls across animation edit routes 2026-10-30 02:29:16 +01:00
Egon 5000 34aef98725 UI: double-clicking a creation tool in the Tools bar makes an instance (#1072)
A double-click on a creation tool in the Tools bar makes what it draws, as in After Effects: a text layer from the Type tools; from the shape tools a shape that fills the comp - into the selected shape layer's Contents, as a mask on the selected layer (or when Tool Creates Mask is on), or as a new shape layer when neither applies. The shape geometry defaults now match AE: the Rounded Rectangle tool's Roundness is a fixed 20 instead of growing with the drawn size, and the Polygon tool draws five points.
2026-10-29 19:52:55 +01:00
aiongg 35e66b17a6 refactor(engine): move tests_<topic>.rs files to src/tests/, tests.rs content to tests/session.rs 2026-10-26 21:49:11 +00:00