Commit Graph
898 Commits
Author SHA1 Message Date
Marco Arnulfo 3aaefab270 UI: the interface symbols test checks the drawn glyph, not has_glyph
epaint's has_glyph compares face keys, so a glyph drawn by the replacement
face reads as missing. With no face in the stack covering egui's `◻`, Inter's
`?` becomes the replacement and Inter's `•` fails the check, which happens
once another test (the #1141 one) has loaded a system face without `◻`: the
fallback tries loaded faces first. Compare the drawn glyph with the
replacement glyph instead, as assert_drawn already does.
2026-10-13 04:17:16 +02:00
tylerjenningsw 544d46a218 Workspaces: a failed save says a restart may undo the changes (#696) 2026-10-12 22:03:01 -04:00
tylerjenningsw e643457fa3 Commands: an earlier invocation's frontend failure isn't a later command's result (#696) 2026-10-12 22:03:01 -04:00
Marco Arnulfo 3db5aebb33 Graph editor: speed graph handles keep dragging once their key leaves the plot (fixes #1171) 2026-10-13 03:47:24 +02:00
tylerjenningsw 41b04bf414 Workspaces: tests for a failed, a storage-less and an on-disk workspace save (#696) 2026-10-12 21:32:22 -04:00
tylerjenningsw b9a9a0a414 Workspaces: Save, Save As, Rename and Delete fail when the file isn't written (#696) 2026-10-12 21:32:18 -04:00
tylerjenningsw 73ea427015 Commands: a frontend-only command's own failure is its result (#696) 2026-10-12 21:31:16 -04:00
tylerjenningsw bf911d18bc Layer Styles: OK and Cancel stay in view (#1062)
The Layer Style dialog's OK and Cancel came after the style list and
the style's controls in one scroll area, and at its usual size they
were laid out past the dialog's bottom edge: clipped, and a click on
them did nothing until the dialog was scrolled.

The dialog now uses above_footer: OK and Cancel sit at its bottom right
and the list and the controls scroll above them, also at 200 % UI
Scale.

Test: layer_style_buttons_stay_in_view (both buttons painted whole and
clicked, at 100 % and 200 %; fails before: Cancel isn't painted).
2026-10-12 21:24:43 -04:00
tylerjenningsw bcfb25ca93 Dialogs: share the buttons-first layout Settings uses
Settings keeps its buttons in view by laying them out first, at the
bottom of its body, and giving its pages the height left above them,
clipped to it. That layout is now dialogs::above_footer, so other
dialogs can keep their buttons in view the same way. Settings looks and
works as before.
2026-10-12 21:24:41 -04:00
tylerjenningsw 765915e126 Workspaces: deleting the current workspace saves after switching to Default (#696) 2026-10-12 21:07:39 -04:00
Kristian MyramandClaude Haiku 5.5 863a6aff6c #1167: frames: keep the viewer frames when only plain markers change
Adding a marker replaced the comp, so every cached frame stopped matching and the preview had to
re-render before its audio could carry on. Plain markers change no pixels; protected time markers
with a duration still do (Responsive Design). Markers count in full again when a project uses
expressions, which can read them.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-13 02:20:31 +02:00
Kristian MyramandClaude Haiku 5.5 9e8112499c #1167: test: a marker edit keeps the viewer frames (fails on main; reproduces the audio pause)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-13 02:20:31 +02:00
Marco Arnulfo 56f6612f78 Dialogs: drag a modal dialog by its title to move it off the viewer (fixes #1155) 2026-10-13 02:02:46 +02:00
tylerjenningsw bfb7507565 Timeline: a Quick Offset of layer bars ends on release off screen (#1012)
The layer bar Quick Offset was followed and ended in its row's code, and
rows out of view aren't drawn. Released with its row scrolled away, it
stayed active: the next drag of that bar, even a plain one, ran as a
Quick Offset from the old origin, into the old undo step.

Like the key drag, it now follows the pointer below the rows and ends
when the button is released, wherever the bar's row is.

Test: a_quick_offset_released_off_screen_ends (release with the row
scrolled away; a plain drag after it moves both layers together as its
own undo step; fails before).
2026-10-12 18:49:51 -04:00
tylerjenningsw e2d50ec926 Timeline: Shift ranges and key boxes stagger in comp order (#1012)
In After Effects a marquee selection staggers in the comp's layer order,
not in the direction the box was drawn. A Shift-click range of layer
bars and a box of keys already come out top layer first; this test makes
both with the pointer (the range from the bottom layer up, the box from
the bottom right to the top left) and checks the Quick Offset that
follows: the top layer stays and the bottom one moves the whole delta.
2026-10-12 17:45:30 -04:00
Marco Arnulfo d85601f8eb UI: a Simplified Chinese interface picks a face with the simplified hanzi (fixes #1141)
The Chinese UI fallback was chosen by probing 文, which Japanese faces
cover too. Fallback takes a face already loaded first, so after the
English interface had loaded a Japanese face for kana, switching to
Simplified Chinese reused it, and the simplified-only hanzi (选, 删,
层, 设, 页 ...) drew as boxes. A Simplified Chinese interface now probes
页, as wordcraft does for its interface font (storytold/wordcraft#248).
2026-10-12 23:38:13 +02:00
tylerjenningsw 94b4d0ca34 Timeline: Quick Offset layers and keyframes in selection order (#1012)
Ctrl/Cmd+Alt dragging a selected layer bar or a selected key now runs a
Quick Offset (layer.quickOffset / keys.quickOffset with fromStart, one
undo step). The mode is chosen when the drag starts and needs at least
two unlocked layers; the last selected layer moves by whole frames with
the pointer. A readout by the pointer shows the Total Offset and the
offset Per Layer, translated.

A plain drag still moves the selection together, Alt alone still scales
a key group in time (it now leaves Ctrl/Cmd+Alt to Quick Offset), and
Ctrl/Cmd+Alt+click still toggles Hold. The key drag's readout is drawn
by a shared drag_tip. Keys also register timeline.keyAt.<uid>.<ticks>,
exact where keys on subframes can share a frame.

Tests (ui_quick_offset): staggering layer bars in selection order and
keys per layer, one undo each; plain drags and Alt scaling unchanged; the
readout while dragging.
2026-10-12 17:37:34 -04:00
FredApps b4e7f8615f Timeline: the Video-off notice takes the frames/fps line instead of overlapping it (#1118) 2026-10-12 23:30:14 +02:00
Egon 5000 4101cef8b4 UI: add an Effects submenu to the layer context menu
The layer context menu gains an Effects submenu between Blending Mode and Arrange, mirroring the After Effects layer menu: the effect registry grouped by category (sorted), synced with the Effect menu; picking one applies it to the selected layers.
2026-10-12 23:03:39 +02:00
pravdomilandClaude Opus 5.5 a3e2271e94 Viewer eyedropper: stay armed until there is a frame to sample
A colour pick clicked in the Composition panel before the viewer had a frame
(still rendering on a background thread, or a readback pending) sampled nothing
but was used up, leaving the colour unchanged. The click now leaves the
eyedropper armed, as the text colour eyedropper already does.

timeline_colour_eyedropper_samples_the_comp clicked without waiting for the
frame and hit this in about one run in four; it now waits for the frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:52:38 +02:00
FredApps 463a4a5221 Preview: say so in the viewer and Timeline when Video is off (#1118) 2026-10-12 22:25:40 +02:00
pravdomilandClaude Opus 5.5 5789c1c7d8 Scroll bars: a handle you can see [skip ci]
The handle was filled with the colour of its own track (both the field
background), so it only showed while hovered or dragged. It now takes the text
colour, in every scroll area.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:49:05 +02:00
pravdomilandClaude Opus 5.5 00afd27dca Keyboard Shortcuts: Enter is OK [skip ci]
Enter closes the editor like its OK button, also while the search field has
focus. It stays with the shortcut recorder (Enter can be recorded), the preset
rename field and an open preset menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:42:40 +02:00
pravdomilandClaude Opus 5.5 e91b19f2a5 Floating panels: no widget ID clash when dragged past the window edge [skip ci]
The floating group's title strip used the same id as its Area's own
background widget, and the Area was shifted back into the window while
the group's rect kept moving, so the two no longer overlapped and egui
painted "Double use of widget ID" over the panel. The strip has its own
id and the group is drawn where its rect says.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:39:27 +02:00
pravdomilandClaude Opus 5.5 07fe9cb1dc Keyboard Shortcuts: keep the OK button in view [skip ci]
The editor's content was a little taller than its dialog, so the outer scroll
area clipped the OK button and its scrollbar covered the right edge. The dialog
now has no outer scroll area: the command list takes whatever height is left,
so the button row always fits, in small windows too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:34:56 +02:00
Marco Arnulfo 8e21e5dbc1 Tracker: a track point can be grabbed when zoomed out (fixes #1067)
The attach point's 12 px grab area sat on top of the feature region and is tested first. Zoomed out, a default feature region is smaller than that on screen, so every press inside it moved the attach point instead of the point. Inside the feature region the attach point now grabs only the region's inner half.
2026-10-12 21:22:01 +02:00
vangel76andClaude Sonnet 5.5 51371939ad Gap 7: Backgrounds animation presets (#1096)
Problem: the built-in animation preset library had no Backgrounds category
(gap 7: 31 presets against After Effects' 621).

Fix: 23 original Backgrounds presets in crates/engine/presets/backgrounds.json,
built from our own generator, noise, colour and stylize effects: Soft Gradient
Drift, Aurora Veil, Slow Fog, Cloud Bank, Dark Smoke, Ember Haze, Magma Flow,
Ice Flow, Pastel Plasma, Cell Drift, Crystal Facets, Hex Mosaic, Mirrored Silk,
Water Caustics, Blueprint Grid, Checker Scroll, Scrolling Stripes, Pulse Rings,
Bokeh Drift, Spotlight Floor, Dawn Sky, Sweeping Light, Grainy Wash.

The preset format gains `expr` (an expression per property, so backgrounds keep
moving for the whole layer) and point parameters written as fractions of the
layer size. Effects & Presets lists them under * Animation Presets > Backgrounds.
Tests: catalogue uniqueness and categories, apply/undo/redo of every preset
(engine), render of every preset with the expression engine: finite,
non-flat, deterministic, moving (host), panel listing and apply (ui-egui).
Sidecar, ATTRIBUTION.md, gaps.md row 7 and effects-parity.md updated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:13:05 +02:00
pravdomilandClaude Opus 5.5 97514ef198 Fix #978: keep form choices and buttons inside the dialog
Undoes the 800 px Project Settings width from #980: the form is back at the
shared 480 px.

A form's choice popup keeps its 240 px column and ends a long choice (a GPU
adapter's name) in an ellipsis instead of widening the grid past the dialog.
Only the fields scroll, and only vertically; OK and Cancel sit under the
scroll area, so they stay in view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:11:01 +02:00
pravdomilandClaude Opus 5.5 af28bc4ddb Shortcuts: C cycles the camera tools
tool.camera cycles Orbit, Pan and Dolly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:09:49 +02:00
pravdomilandClaude Opus 5.5 81521d9b06 Shortcuts: switch, cycle and close panels
window.toggleCompTimeline (\) switches between the Composition viewer
and the Timeline. window.previousPanel / nextPanel (Alt+Shift+, / .)
step through the tabs of the focused panel's frame. window.closeAll
(Cmd+Shift+W) closes every open composition when a viewer or the
Timeline is active, otherwise the focused panel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:08:43 +02:00
vangel76andClaude Sonnet 5.5 f11792827e Gap 21: percentage guides and effect colour labels (#1095)
Guides can store a percent of the comp so they follow comp-size changes
(View > Add Percentage Guide, Convert Guides to Percentage / Pixels); an
effect instance has an optional colour label (effect.setLabel, Effect Controls
header bar and Label menu). Both are serde-defaulted, so old projects load.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:07:36 +02:00
pravdomilandClaude Opus 5.5 00799d8c77 Shortcuts: fit up to 100 %, step through open comps
view.fitUpTo100 (Alt+/) fits the viewer without magnifying past 100 %.
view.previousItem / view.nextItem (Shift+, / Shift+.) activate the
previous / next open composition, wrapping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:06:24 +02:00
pravdomilandClaude Opus 5.5 f7b366197d Shortcuts: scroll the Timeline, Parent column
timeline.scrollToTime (D) centres the current time in the time graph,
timeline.scrollToLayer (X) puts the topmost selected layer at the top;
both are done when the Timeline is next drawn. timeline.parentColumn
(Shift+F4) shows or hides the Parent column.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:04:50 +02:00
pravdomilandClaude Opus 5.5 bf53ae6094 Shortcuts: layer selection, timing, masks and Casts Shadows
- layer.extendSelectionNext / Previous (Cmd+Shift+Down / Up).
- layer.moveInToStart / moveOutToEnd (Alt+Home / End).
- layer.moveEarlier / moveLater (Alt+PageUp / PageDown) and
  layer.moveEarlier10 / moveLater10 (with Shift). Alt+PageUp / PageDown
  used to slip the source one frame; layer.slipBack / slipForward keep
  working but have no default key.
- layer.stretchInToTime / stretchOutToTime (Cmd+Shift+, / Cmd+Alt+,):
  layer.timeStretch takes to: in|out.
- layer.mask.selectNext / selectPrevious (Alt+` / Alt+Shift+`).
- layer.castsShadows (Alt+Shift+C) for the selected 3D layers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:02:49 +02:00
pravdomilandClaude Opus 5.5 c6a87a2798 Marker dialog: Cmd+Enter is OK, also from the Comment field [skip ci]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:00:49 +02:00
pravdomilandClaude Opus 5.5 cf912d5049 Shortcuts: deselect keyframes and properties
keys.deselectAll (Shift+F2, Cmd+Alt+Shift+A) clears the selected
keyframes, properties and groups and leaves the layers selected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:59:48 +02:00
pravdomilandClaude Opus 5.5 d444eceb90 Shortcuts: work area from the selection, most recent comp
comp.workAreaToSelection (Cmd+Alt+B) spans the selected layers, or the
whole composition with none selected. comp.activateRecent (Shift+Esc)
goes back to the composition that was active most recently within the
active one's nesting hierarchy; EditorState keeps recent_comps for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:57:21 +02:00
pravdomilandClaude Opus 5.5 a644bb07c9 Shortcuts: go to the work area ends and to In / Out points
time.workAreaStart / time.workAreaEnd (Shift+Home / End) and
time.previousInOut / time.nextInOut (Cmd+Alt+Shift+Left / Right): the In
and Out points of the selected layers, of every layer with none selected.
time.go takes nextInOut and prevInOut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:53:49 +02:00
vangel76andClaude Sonnet 5.5 8703f52d12 #1042: path vertices win over the bounding-box handles in the viewer
A vertex under or beside a box handle lost the press to the handle (the handle reaches 9 points, the vertex 6), the resize cursor showed over it, and the handles were painted over the vertex markers. Vertex reach now matches the handle's wherever one is in range, the cursor stays a pointer, and markers are drawn last.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 20:31:48 +02:00
Elias b00c7f582a ui: centre Reset / About... on the effect header row in Effect Controls
The buttons were offset 2pt below the 22pt header's centre, so their text sat
below the effect name's baseline.

(cherry picked from commit acacef9f42e992c535397a55ae03bb3f3684a5e0)

(cherry picked from commit dc9ff1b5aad75c4f4233d89ed33813844e980487)
(cherry picked from commit 1e599b6e1d2e3402a10477ccccd1fd52724dc95c)

(cherry picked from commit 7deda99fabe57bb40c6ea9f02f18c6c79d19d792)
2026-10-12 19:22:18 +01:00
Elias 5bcfc0a4a5 ui: elide long Project panel names with an ellipsis
Names were hard-clipped mid-glyph against the label column
("EffectCraft Intrc"); use widgets::text_fit like the other text columns.

(cherry picked from commit 341c924eff265f08e8b04b5a6a99d0d173a13e24)

(cherry picked from commit 60086aa4b5c735cd2307d773b22d8189e211f40f)
(cherry picked from commit c318f8438f60d5ecb8bbebb8857bad1fe6d9834d)

(cherry picked from commit eaebbe7ce0b9d88970f435e9327f7b04612c1a9d)
2026-10-12 19:22:18 +01:00
Elias 5b2b99464d ui: skip timeline ruler labels that would run under the marker bin
The comp-end label was clipped to a stray "1" against the marker bin.

(cherry picked from commit f62afa0364f1bf38f0b0b5eda5ccc07f33174790)

(cherry picked from commit 2e3d08dad7d73a14688bf6d8bfb1712ab51443a2)
(cherry picked from commit 773471c3a39bef51f4763d21d007534cfd95c0b1)

(cherry picked from commit 176508a82145eb7063c776f6cd44ba925a8edd99)
2026-10-12 19:22:17 +01:00
Elias 9af5560c1f UI: let Type tool edit selected overlapping text while respecting visibility
(cherry picked from commit 9fd5b1e5618a6ad19638494b480460e9527debde)

(cherry picked from commit 812e34fd7834e828bebd3f79440f831d188a1a99)
(cherry picked from commit 283adb1a30e6b51ab6603488e57b9997a0ca83f0)

(cherry picked from commit cb2e659baad5e4fe853c124dafe32491335b8232)
2026-10-12 19:22:17 +01:00
Elias 66812324c9 UI: reproduce overlapping duplicated text editing with pointer and Type tool
(cherry picked from commit 0acb03da5f0d09d726047013e931e5eeff5504ce)

(cherry picked from commit 66427c0149c5f2fd46931945a4f11a9530c12269)
(cherry picked from commit d5fadffc1ac9f072a985a918cd6a62e9763bc2bf)

(cherry picked from commit adec1c33542c2566183c6698cb0b1ad8e8afa0e0)
2026-10-12 19:22:16 +01:00
Elias def8b6f3b4 Timeline: a click on empty track area deselects layers (as in After Effects)
(cherry picked from commit 9d6352faea454ebcd1a575056c4d5f0bafcc80ea)

(cherry picked from commit d6110a23e9c459eb4c677b439d811b7438b1a999)
(cherry picked from commit f46595d119d253c9298eb045ad521420a155b422)

(cherry picked from commit fff43e6f6edc00bf60aa031643f3356b9e7ccfad)
2026-10-12 19:22:16 +01:00
Elias 223b21b06a timeline: trim zones straddle layer bar ends (AE), trim wins over slip
The In/Out trim zones were 6 pt strips inside the bar only: at or just outside an end the pointer got the default cursor, and on footage/precomp layers just outside the end it hit the slip zone, which shows the same arrow but slips the source instead of trimming. Zones now reach 4 pt outside and up to 5 pt inside each end (short bars keep their middle third as body), registered after the slip zones so trimming wins there. The trim zones show the system resize cursor (upstream port: the fork also offers an owner-local cursor, left out here). Test: ui_timeline_trim.

(cherry picked from commit e2490f801067365addc03858bd555731cb188ad1)

(cherry picked from commit b704fc52c4fdb43816721e95d13f132a11062aa1)
(cherry picked from commit 17faf9cebf9e347534ceab37386e79979da8f786)

(cherry picked from commit 9b9d21aacc4d025e36e13a05e4416a49f448bdf1)
2026-10-12 19:22:15 +01:00
Elias 520ea11059 ui: timeline view stops at the comp end; a ruler scrub past the edge scrolls with the CTI
Co-Authored-By: Claude <noreply@anthropic.com>

(cherry picked from commit 562bfa51bd6ee86d1f8f5558b1ad466c7e4b4517)

(cherry picked from commit 0779d6944ede8afdff6ab49ea5d2caad19dfbfa3)
(cherry picked from commit 38e224f5c5037b7c79a283ab058582a3ad200339)

(cherry picked from commit 5e7b68be23ace400d92672ebf41c59124d29b101)
2026-10-12 19:21:42 +01:00
Elias c4fdbd6064 ui: Graph Editor fit goes through the timeline zoom; AZERTY zoom keys in the graph
Co-Authored-By: Claude <noreply@anthropic.com>

(cherry picked from commit 6277a98f3ff6207bd215213af514c5f6fb481532)

(cherry picked from commit 646f4055b180d98ccc6ac6898b64ba97f9e2ad7d)
(cherry picked from commit b21932ed7058cec68da01d337ba46521501ebc49)

(cherry picked from commit 0d6b93962e123b2e0179622f2abd472cfa9015ac)
2026-10-12 19:21:42 +01:00
Elias ac442f8c61 ui: Graph Editor fits the selection when it opens
Opening the Graph Editor (header button, menu, Shift+F3, control channel)
frames the graphs on its first frame: Fit Selection to View when keys are
selected, else Fit All Graphs to View. Switching value/speed graph refits
too (different units). A selected key now shows its property's graph even
when its layer isn't selected, and Fit Selection on a lone key also frames
its neighbouring keys.

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

(cherry picked from commit a3c95f601e78e7a12f62aba94ee3515b2ade1670)

(cherry picked from commit d6309ffad79b91676d6409d1845de508e485873d)
(cherry picked from commit 78f557433742e443c9b7db34c1dac67e6a2b8e18)

(cherry picked from commit 7a4e160434b7bf1289cbf5900a86715814d1c791)
2026-10-12 19:21:41 +01:00
Elias 923ec0fc4a ui: Graph Editor follows the timeline time zoom; zoom buttons and slider clicks work
The Timeline footer's zoom-out / zoom-in mountain icons were painted but not
interactive, and the zoom slider only reacted to drags (a click on the track did
nothing) and set the zoom without the whole-comp clamp. The icons are now buttons
(timeline.zoomOutButton / timeline.zoomInButton, one = / - step), the slider
jumps on click, and both go through set_zoom, centred on the CTI.

The layer bars and the Graph Editor share one time zoom (TimelineState start /
pps, as in After Effects); regression tests drive = / -, the buttons, the slider
and the navigator over the control channel in both views and check switching
views keeps the zoom.

Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit 2ee0fb656ff6bd16eed6857be10495d9f30e3a64)

(cherry picked from commit f1997d32d4c51b58467a04944889131fd741a22a)
(cherry picked from commit 1c25aeb51d37357b4b37857858db4dbea246b13a)

(cherry picked from commit 81d7fcccfc91f76f7b9640cbb7d3f75dcea56e30)
2026-10-12 19:21:41 +01:00