Commit Graph
470 Commits
Author SHA1 Message Date
Claude 69bf806ff5 Graph Editor: buttons that don't fit the bar move to a » menu instead of being cut off (#457)
The Graph Editor's bottom bar lays out 17 text buttons in one row
(about 1100 px) on a painter clipped to the graph area, so on a
normal-width Timeline the right-hand ones (keyframe interpolation and
easing) were cut off and unreachable. Buttons that would pass the bar's
right edge now go, in order, to a » menu at its end; picking one there
runs the same action on the next frame. Hidden buttons register as
timeline.graph.more.<id> while the menu is open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 19:16:48 +00:00
Claude e152dfd1d1 Essential Graphics: Scale keeps its Constrain Proportions link, on by default (#338)
A Scale property added to Essential Graphics fell into the generic Point
control: two independent fields with no link, so dragging one value
distorted the layer, unlike After Effects, whose Scale control keeps the
chain link. It now draws the link (on by default) with one field per
axis; linked, an edit scales the others in proportion (Alt edits one),
using the Timeline's constrained() (moved to widgets). The link state is
the property's own, shared with the Timeline's chain link.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 19:16:47 +00:00
Claude 76c9abad50 Viewer: the 3D Renderer menu shows the comp's renderer and switches it (#307)
The Composition panel's bottom bar drew a hard-coded "Classic 3D"
dropdown that ignored the comp's renderer and did nothing when clicked,
so an Advanced 3D comp still read Classic 3D. It now shows the comp's
renderer (translated) and, as in After Effects, its menu switches it
through comp.settings (one undo step); the automation label is the
renderer's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 19:16:36 +00:00
Claude bf5e6c6cec #581: the Discord pill fits its label and field text sits on the field's middle
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 19:16:03 +00:00
Claude e4916e5ca9 #513: clicking off a mask's path, even on its layer, deselects its points
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 19:16:03 +00:00
Claude ad7df67602 #360: the Project row menu's New Comp from Selection uses the whole selection
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 19:16:03 +00:00
Claude 7a95a0d138 Project: a single unselected folder or data-file drag still reports why; index math saturates (#634 follow-up)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 18:51:45 +00:00
Claude 954e89c661 Merge pull request #638 from FrederoxDev/feat/color-hex-input 2026-10-10 18:51:16 +00:00
Claude 1c68166b2e Merge pull request #634 from Ni-zav/fix/project-multiselect-drag-351-s20261010T1753Z-f4c2 2026-10-10 18:51:15 +00:00
Claude 5727754a54 Merge pull request #628 from MarekSpodBiedry/issue-505 2026-10-10 18:51:15 +00:00
Claude 6538fb175f Merge pull request #619 from MarekSpodBiedry/issue-546 2026-10-10 18:49:51 +00:00
Claude ea10c73294 Merge pull request #618 from MarekSpodBiedry/issue-547 2026-10-10 18:49:51 +00:00
FrederoxDevandClaude Opus 5.5 c8657bf214 UI: one After Effects-style colour picker with a hex field for every colour input
Every colour input opens one picker laid out like After Effects' Color
Picker: a square and slider for the channel chosen with H / S / B /
R / G / B, the new colour over the original, HSB and RGB fields, a hex
field (#RRGGBB, RRGGBB, #RGB) and OK / Cancel. Changes apply live;
Cancel, Escape and the original swatch restore the starting colour.

The 3D light dialog, Essential Graphics and Layer Styles passed sRGB
values to egui's color_edit_button_rgb(a), which reads them as linear,
so picked colours were stored darker (#808080 became #373737). They and
the other dialogs now use the shared sRGB colour button.

The picker and colour helpers live in color_picker.rs; widgets
re-exports them.

Tests: ui_color_hex.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:26:20 +01:00
Nigel Ihza Firdausy 1922e621c2 fix(ui): drop all selected Project items into compositions (#351)
Preserve Project multi-selection when dropping onto the Timeline or Composition viewer. Keep stack order and drop position, skip non-layer project items, and add pointer-drag regression coverage.
2026-10-11 00:58:35 +07:00
MarekSpodBiedry 068db1f36b Let pan and zoom work while 3D Camera Tracker points are shown (#505) 2026-10-10 19:31:51 +02:00
MarekSpodBiedry ad0fc4da09 Locked viewer: re-convert pixels when the display profile or output simulation changes (#546) 2026-10-10 19:12:02 +02:00
MarekSpodBiedry d5f8fb54cb Viewer: passive Composition viewers apply the monitor color conversion (#547) 2026-10-10 19:11:00 +02:00
Claude 00364546eb Merge pull request #593 from kikikikier/community/type-in-font-search 2026-10-10 16:29:15 +00:00
kikikikier abd44404f8 UI: add inline font family search in Character and Properties 2026-10-10 17:14:06 +03:00
Claude 00e9e37c0a UI: the drop hint and drop errors go through the interface catalog; the Wayland notice points to the README (#447 follow-up)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:55:10 +00:00
Claude 63acbb1eb0 Merge pull request #447 from David-T-Campos/fix/footage-drag-drop
# Conflicts:
#	apps/effectcraft/src/main.rs
2026-10-10 12:54:44 +00:00
Claude a5feb441e9 Merge pull request #499 from tylerjenningsw/enhance/project-shift-delete 2026-10-10 12:51:16 +00:00
Claude 0ce5063d9f Viewer: Ctrl/Cmd draws a shape from its centre, as in After Effects (#443 follow-up)
Also keeps #442's newest-completed-revision lookup for the live drag, so
Frames has one way to pick the frame shown while an edit renders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:51:15 +00:00
Claude b7b47a0e10 Merge pull request #443 from Aavirash/fix/shape-drag-preview
# Conflicts:
#	crates/ui-egui/src/frames.rs
#	crates/ui-egui/src/panels/viewer.rs
2026-10-10 12:50:43 +00:00
Claude 91d37dd449 Merge pull request #423 from cdinhoo/codex/effect-input-control-fixes 2026-10-10 12:50:18 +00:00
Claude b5c6eb7d5e Merge pull request #461 from vbasky/feature/recursive-footage-relink 2026-10-10 12:50:18 +00:00
Claude 790f57ef24 Merge pull request #442 from cdinhoo/codex/live-preview-updates
# Conflicts:
#	docs/architecture.md
2026-10-10 12:50:18 +00:00
Claude 0df89c84ec Merge pull request #579 from KattKnight/windows-test-fixes 2026-10-10 12:49:56 +00:00
Claude f6d130ac38 Merge pull request #512 from sanyamsingh001/fix/settings-info-return 2026-10-10 12:49:17 +00:00
KattandClaude Opus 5.5 a650e6c21d Tests: four failures on Windows (autosave paths, GPU viewer adapter, audio preview race)
- automation / cli autosave restart tests: the MCP instructions embed the
  auto-save state as JSON, so a Windows path's backslashes are escaped there;
  look for the JSON form of the path.
- ui_gpu: egui_kittest prefers a CPU adapter, which on Windows is WARP on
  DirectX 12, where FXC fails to compile the compositor's `pointwise` kernel
  ("compilation aborted unexpectedly"), so the viewer stayed on the CPU and
  the test failed before comparing anything. Build the harness on the adapter
  the headless compositor picked (falling back to egui_kittest's choice).
- ui_audio_scrub (#103 test): with a fixed 2 s comp, a machine with many
  render threads cached the whole preview before the first step, so the sound
  rightly started at once and no silent frame was counted (3 of 24 runs
  failed with 8 copies in parallel). Size the comp to four times the frames
  playback requests per step, so caching takes at least four steps (0 of 24).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:36:52 +05:30
Aavirash 603337a061 Viewer: a layer drag moves the picture while the button is down
Every pointer move replaces the comp's content identity, so the frame on
screen takes a new cache key at every step while its render is still in
flight; the viewer only ever showed an exact key, so the picture froze on
the last completed frame until the drag ended. While a drag or a property
scrub is running, show the newest frame of the same comp, frame, scale,
view and render options that is ready — a render behind, as After Effects
does — and go back to exact frames when it stops.
2026-10-10 12:13:55 +02:00
Aavirash 0d2264dbed Viewer: the shape tools show the tool's own shape while dragging
The drag preview was a 1 px axis-aligned rectangle for every shape tool,
which read as no preview at all against most comps. Draw the tool's own
path instead (rectangle, rounded rectangle, ellipse, polygon, star), from
the engine's own geometry, filled with the Tools bar's Fill and outlined
in its Stroke, with a caption saying where the shape lands — a mask on
the selected layer, into the selected shape layer, or a new shape layer.

The ghost and the released shape go through one normalisation, so the
drag shows exactly what it commits: Alt (Option) draws from the press
point and Shift squares the box, both live. The drag also starts at the
press point now, not where the 6 px drag threshold was crossed, so the
shape is drawn from where the button went down, as in After Effects.
2026-10-10 12:13:21 +02:00
tylerjenningsw 4359899f7a Project: a Cut is read with the modifiers held where it is in the frame (#484)
Cause: clipboard events carry no modifiers, and the Cut and Copy/Paste
mapping read i.modifiers, egui's state after all of the frame's events.
A Shift+Delete with Shift released in the same frame became Ctrl+X (no
deletion), and a Ctrl+X followed in the same frame by Ctrl up and Shift
down became Shift+Delete: the selected items and the layers using them
deleted without the prompt.

Fix: walk the frame's events in order from the modifiers held when it
began (the state the last pass ended with, recorded each pass), so each
Cut, Copy and Paste uses the modifiers at its place in the stream. When
that state isn't known (a pass was skipped), a Cut is never Shift+Delete.
Only Shift alone counts, not Ctrl/Alt+Shift.

Tests: a_cut_is_read_with_the_modifiers_where_it_is_in_the_frame queues
modifier changes and a Cut in one frame (Shift then Cut and Shift up;
Ctrl, Cut, Ctrl up, Shift down; and the mixed orders); the Windows
Shift+Delete helper now sends Shift, Cut and Shift up as one frame. They
fail on the previous mapping and pass now.
2026-10-09 19:55:48 -04:00
sanyamsingh001andCodex e4ca1e919a G2: return to Settings after dismissing GPU Information
Preserve pending preference edits through the existing OK and Cancel actions.

Co-authored-by: Codex <codex@openai.com>
2026-10-10 08:46:03 +10:00
tylerjenningsw a65d70f10e Project: Shift+Delete deletes the selected items without asking (#484)
With the Project panel focused, Delete Project Items Without Confirmation
runs project.delete on the selection: items compositions use go without
the prompt, with their layers, in one undo step. In the other panels it
does nothing, and like every shortcut it doesn't fire while typing or
with a dialog open.

On Windows the windowing layer sends Shift+Delete as Cut (the old Cut
key), which was mapped to Ctrl+X: in the Project panel, which has no
clipboard, a Cut with only Shift held is Shift+Delete now. Elsewhere it
still cuts.

Tests (ui_project_delete): Shift+Delete as a key and as Windows' Cut
deletes a comp, a solid in use, footage and a folder without the prompt
and one undo restores them; a multi-selection with a folder holding a
solid in use goes together; an empty selection deletes nothing; the next
Delete still asks after Shift+Delete or an answered prompt; it does
nothing in the Composition panel, while renaming or with a dialog open;
Shift+Backspace, Alt/Ctrl+Delete and Ctrl/Alt+Shift+Delete don't delete.
The deleting tests fail without this change.
2026-10-09 16:27:48 -04:00
bflatasticandClaude Opus 5.5 67305fbcd1 Viewer: each composition keeps its Resolution in the project, as in After Effects (#417)
What: the Composition panel's Resolution (Auto, Full, Half, Third, Quarter, Custom) is now a
property of the composition (`Comp::resolution`, moved with its `Resolution` type from the UI
into the project crate) instead of one global viewer setting. Switching to another comp shows
that comp's resolution, switching back shows the first one's again, and saving and reopening the
project keeps them. `view.res.full|half|third|quarter|custom` and the new engine command
`view.res.auto` set it (headless too, with an optional `comp`); `ui.set {viewer: {res}}` sets
the active comp's and `ui.inspect` still reports `ui.viewer.res`; `comp.info` reports
`resolution` and `resolutionFactor`; View ▸ Resolution's check marks come from the engine.

Why: After Effects saves each composition's Resolution with the project (CompItem.resolutionFactor
is a per-comp attribute). As there, changing it marks the project modified but adds no undo step:
undo, redo and History jumps carry the current values over to the restored state. It is not part
of the comp's pixels (`Comp::same_pixels` ignores it and `Comp::pixel_form` normalises it), so
changing it keeps the comp's RAM and disk cache keys. Auto is not written (serde default and
skip_serializing_if), so projects saved before open with Auto and older versions read new files.
The magnification is not saved per comp: Adobe's documentation doesn't say it is.

Tests: project `comp_resolution_is_saved_and_old_projects_load_with_auto`,
`resolution_factors_and_scales`; engine
`each_comp_keeps_its_resolution_outside_the_undo_history_and_in_the_file` (switching comps,
no undo step, undo/redo keep it, save/open round trip, menu check marks, Custom dialog);
ui-egui `each_comp_keeps_its_viewer_resolution` (the viewer popup on comp A, comp B through
`ui.set`, back to A, unchanged frame cache identity, save/open). They don't build before the
change (no `Comp::resolution`, no `view.res.auto` engine command).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:57:00 +07:00
bflatasticandClaude Opus 5.5 98a6a3a041 UI: Arabic, Hebrew, Indic and Thai names can be typed and are drawn (#394)
Cause: two things kept Arabic out of a layer name on Windows.
- Windows switches the keyboard layout with Alt+Shift. Releasing Shift
  before Alt left Alt held alone, and the in-window menu bar (#279)
  counted the release as an Alt tap: it took the keyboard focus, the
  rename field closed, and the letters typed next were swallowed by the
  menu bar. The Project panel's rename field lost them the same way.
- The UI fonts are Inter plus the CJK system fallbacks, so Arabic,
  Hebrew, Indic and Thai names that did arrive (pasted, or from a
  project) showed as missing-glyph boxes.

Fix:
- An Alt tap only counts when Alt went down with no other modifier
  held, so Alt+Shift in either release order is no tap; a plain Alt tap
  still focuses the menu bar.
- The UI registers installed system faces for Arabic, Hebrew, Devanagari,
  Bengali, Gurmukhi, Gujarati, Tamil, Telugu, Kannada, Malayalam and Thai
  after the CJK ones, the same way (native only; the web build has no
  system fonts). A face covering several scripts is registered once
  (Segoe UI: Arabic and Hebrew; Nirmala UI: every Indic script).
- The text engine's fallback tries each script's plain platform families
  (Segoe UI, Nirmala UI, Leelawadee UI, Geeza Pro, Kohinoor, Noto…)
  before any covering face, so neither the UI nor a text layer gets a
  calligraphic face that merely sorts first.
- The Timeline's rename field registers `timeline.layer.<id>.nameEdit`.

egui 0.36 shapes each run of one face, so Arabic letters join and a word
reads right to left; it has no bidirectional layout, so the words of a
multi-word Arabic name (and mixed Arabic/Latin) still follow each other
left to right.

Tests: ui_inline_edit a_layout_switch_keeps_the_name_field_and_arabic_
names_are_kept (Alt+Shift both ways in the layer rename, Arabic typed and
stored; Hebrew/Devanagari/Thai in the Project panel; a plain Alt tap
still focuses File; failed before: the field closed), theme
installed_script_fallbacks_draw_arabic_hebrew_indic_and_thai_names
(failed before: replacement glyph for Arabic) and
arabic_words_are_joined_and_read_right_to_left, text
other_scripts_fall_back_to_a_plain_system_family and the script
classification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:53:21 +07:00
Vikram Bhaskaran db6b2e8079 Relink missing footage by scanning a folder for compatible files.
A same-named file is used only when kind, size, codec, and for moving pictures the rate and duration agree. Symlinks are not followed, and duplicate names are left alone.
2026-10-10 04:37:44 +11:00
bflatasticandClaude Opus 5.5 67b9b20a07 Timeline: every property has a pick whip in the Parent & Link column (#363)
What: each property row that can take an expression (it has a stopwatch) now
has a property pick whip in the Parent & Link column, as in After Effects
CC 2018 and later (automation id `timeline.prop.<uid>.propertyPickWhip`).
Dragged onto another property's name or one of its values, it runs
`prop.pickWhip`: the reference is added as the property's expression, or
replaces the one it has, and the expression is enabled. A drop on one value
picks that dimension (`position[1]`).

The parent, expression and property pick whips share one widget and one
drop path (rubber band, autoscroll, dimension pick); only the expression
pick whip inserts at the cursor of an expression being edited.

Pick whips (expression and property) now also drop on properties in
Effect Controls: its property rows register as targets while a pick whip
is dragged, with their per-dimension value fields.

Why: the last part of #363. Adobe's docs say the Property Link pick whip
adds the expression without enabling expressions first, and a pick whip
outside an edit replaces the whole expression text. No modifier keys for
the property pick whip are documented, so none are implemented.

Tests: `the_property_pick_whip_links_a_property_to_another` (ui_inline_edit)
drops it on a property's name, on one of Position's values, on a property
with a disabled expression (replaced and enabled), on an Effect Controls
slider and one value of a point, and on itself (no change). It fails
before the change; with Effect Controls' targets removed it fails at the
slider. Looked at the result with the headless snapshot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:28:22 +07:00
David Campos f1839dd180 ui: import native file drops with drop-target hint (ui_drag_drop.rs)
Add tests for file drop behavior and error handling.
2026-10-09 20:37:39 +04:00
cdinhoo e445877494 UI: keep live previews updating during rapid edits 2026-10-09 19:06:17 +03:00
bflatasticandClaude Opus 5.5 79bf5a6b59 Timeline: property names have the property menu (#407)
Right-clicking a property's name in the Timeline did nothing, so
Position's dimensions could be separated only from the Graph Editor.

As in After Effects, it now opens the property's menu: Reset, Edit
Value…, Separate Dimensions (Position and, once separated, X / Y / Z
Position, checked), Add / Remove Expression and Add Property to
Essential Graphics. Only Position separates, as in After Effects
(Scale stays one property).

`prop.reset` without `default` used to leave the value as it was: it
now gives the property its own default (an effect parameter's, or a
Transform property's, shared with Layer ▸ Transform ▸ Reset), which
also makes the Properties panel's Reset reset the values. `prop.set
{layer, prop}` without `value` opens the value dialog, like
`keys.set`.

Tests: timeline_property_names_have_the_property_menu
(ui_blank_context_menus), reset_gives_a_property_its_default (engine).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:52:56 +07:00
bflatasticandClaude Opus 5.5 9c9e954ee2 Timeline: Tab moves to the next value field (#361)
Tab in a value being typed (hot text) dropped the keyboard: egui moved
the focus to the next widget, and the inline editors asked for the
focus again every frame, which also reset what keys a field keeps for
itself.

As in After Effects, Tab now commits the value and types in the next
value field of the same panel (the next dimension, then the next
property's), Shift+Tab the previous one. The hot-text fields of each
panel register in drawing order; the dock tags each panel's Ui so the
order stays within it. `keep_focus` asks for the focus only when the
field doesn't have it.

Tests: tab_commits_a_value_and_moves_to_the_next (ui_inline_edit:
Timeline and Effect Controls).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:52:56 +07:00
bflatasticandClaude Opus 5.5 0171eb1e2e Timeline: the expression field grows while typing and drags taller (#371)
The inline expression field took its height from the saved
expression, so lines typed into it ran over the rows below until the
expression was committed.

Its height now comes from the text being typed (up to 8 lines, as
before), and its bottom edge drags it to any height in whole lines, as
in After Effects; the dragged height is kept per property in the
Timeline state (`expr_lines`).

Tests: the_expression_field_grows_while_editing_and_drags_taller
(ui_inline_edit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:52:56 +07:00
bflatasticandClaude Opus 5.5 6fadae2818 Timeline: the pick whip picks the dimension it is dropped on (#363)
Dropping the expression pick whip on one of a property's values (the X
of Position) referenced the whole property. As in After Effects, a
drop on one value now picks that dimension: `transform.position[0]`;
a drop on the name still picks the whole property.

`prop.pickWhip` takes `target.dimension`.

The rest of #363 is unchanged: inserting at the cursor landed with
#284, and After Effects' property pick whip in the Parent & Link
column is left for later.

Tests: pick_whip_picks_one_dimension_of_the_target (engine),
the_expression_pick_whip_picks_the_dimension_it_is_dropped_on
(ui_inline_edit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:52:56 +07:00
bflatasticandClaude Opus 5.5 639342a5e7 Timeline: the pick whip scrolls the layers at their edges (#362)
A pick whip dragged to the top or bottom of the Timeline's layers left
them where they were, so a property out of view couldn't be picked.

While a pick whip (expression or parent) is held within a row of the
top or bottom edge of the layers, or past it, the layers scroll that
way, faster the deeper, as in After Effects.

Tests: the_pick_whip_scrolls_the_timeline_at_its_edges
(ui_inline_edit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:52:56 +07:00
bflatasticandClaude Opus 5.5 0b2ef8e584 Timeline: Ctrl/Cmd-click on the time display toggles Timecode / Frames (#370)
The Time Display Style could only be changed in Project Settings. As in
After Effects, Ctrl-click (Cmd-click on macOS) on the current-time
display of the Timeline or the Composition panel now toggles it between
Timecode and Frames (Feet + Frames goes to Timecode). It runs
`file.projectSettings {timeDisplay}`, so it is one undo step.

Under the Timeline's display the other style shows now (frames under
timecode, timecode under frames), as in After Effects; it always showed
frames.

Tests: ctrl_click_on_the_time_display_toggles_timecode_and_frames
(ui_inline_edit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:52:56 +07:00
bflatasticandClaude Opus 5.5 fcf3bb5dca Viewer: resize cursors follow each handle and the layer's rotation (#393)
Every bounding-box handle in the Composition viewer showed the
north-west / south-east resize cursor, so two corners and all four
edges showed the wrong direction.

Each handle now takes the cursor along the direction it scales, worked
out from the on-screen box: a corner points between its two edges (the
box's diagonal whatever its proportions), an edge handle across its
edge. The cursors turn with the layer's rotation, as in After Effects.

Tests: handle_cursors_follow_each_handle_and_the_layer_rotation
(ui_viewer: a wide box at 0°, 90° and 45°).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:52:56 +07:00
bflatasticandClaude Opus 5.5 8c4a3cbfe0 Export: a Render Queue job renders every frame on the project's renderer (#414)
Cause: pipeline::Cx rendered with Backend::Auto, which picks the CPU or the
GPU compositor for each top-level frame from measured frame times
(render::AutoPick: warm-up on both sides, a re-probe every 48 frames). The
two compositors differ slightly, so frames came out differently depending
on which side the timings favoured in that run, and two GPU exports of the
same frames differed.

Fix: the job renders every frame on the project's renderer, as After
Effects renders a job with one renderer: Backend::Gpu with Mercury GPU
Acceleration (frames the GPU declines still render on the CPU, as they do
in every GPU render), Backend::Cpu with Mercury Software Only. The viewer
and previews keep Auto. Docs (architecture, parity, web) say so.

Tests: render_settings::a_job_renders_on_one_compositor exports ten frames
with a stand-in GPU compositor that keeps Auto history and draws solid
green: with Mercury GPU Acceleration every frame is green and two runs are
identical (with Auto the warm-up sent frames to the CPU: it fails), with
Software Only the stand-in is never asked. The web worker GPU job test's
comment no longer describes Auto.

Diagnosis by @pat-the-wizard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:26:17 +07:00
bflatasticandClaude Opus 5.5 82f0cd9668 UI: Effect Controls and the Timeline have no parameter row separators, as in After Effects (#402)
#402 made Effect Controls' rows compact and aligned, as After Effects
draws them, and also added thin separator lines between parameter rows
in Effect Controls and the Timeline, with a Settings > Appearance > Show
Parameter Row Separators preference. After Effects has neither, so the
lines, the preference and the Tokens field go; the compact rows, the
alignment and the automation ids stay.

Saved settings with the old key load as before (unknown keys are
ignored).

Test: ui_parameter_spacing keeps the row geometry, hit target and
nesting tests; the separator tests go with the feature.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:13:31 +07:00