mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-24 10:09:01 -06:00
docs/parity-checklist.md: newer header (2026-10-21); both revision rows.
This commit is contained in:
@@ -643,6 +643,11 @@ impl LightcraftApp {
|
||||
// Keep it hidden after release; O / the overlay eye can show it again.
|
||||
self.ui.mask_overlay = false;
|
||||
}
|
||||
if r.is_ok() && matches!(id, "mask.add" | "mask.addComponent" | "mask.duplicate" | "mask.select") {
|
||||
// A new or newly picked mask shows its overlay again, as in Lightroom: hidden by a slider
|
||||
// drag above, it stayed hidden while the Overlay menu still named a mode (issue #1800).
|
||||
self.ui.mask_overlay = true;
|
||||
}
|
||||
if r.is_ok() {
|
||||
// These commands finish synchronously, so their completion would otherwise
|
||||
// be invisible once the activity stack is gone. Never show success on error.
|
||||
@@ -833,6 +838,8 @@ impl LightcraftApp {
|
||||
ctx.request_repaint();
|
||||
}
|
||||
if let Some(mask) = polled.refine {
|
||||
// a new selection from a click or a description: show it, as `run` does for new masks
|
||||
self.ui.mask_overlay = true;
|
||||
self.ui.detail_due = Some((now + 0.3, mask));
|
||||
}
|
||||
if let Some(e) = polled.messages.into_iter().last() {
|
||||
|
||||
@@ -192,6 +192,37 @@ fn mask_adjustments_hide_overlay_without_disabling_the_mask() {
|
||||
h.settle(SETTLE);
|
||||
}
|
||||
|
||||
/// A slider hides the overlay (above); a new mask, an added part, a duplicate or picking a mask in
|
||||
/// the list shows it again, so the Overlay menu's mode is what the photo shows (issue #1800).
|
||||
#[test]
|
||||
fn a_new_or_picked_mask_shows_the_overlay_hidden_by_a_slider() {
|
||||
use lightcraft_pipeline::Overlay;
|
||||
let mut h = detail("panel.masking");
|
||||
exec(&mut h, "mask.add", json!({"kind": "linear", "start": [0.5, 0.2], "end": [0.5, 0.7]}));
|
||||
let first = h.app.session.active_mask.unwrap();
|
||||
let hide = |h: &mut Headless| {
|
||||
exec(h, "mask.adjust", json!({"values": {"exposure": 0.5}}));
|
||||
assert!(!h.app.ui.mask_overlay);
|
||||
};
|
||||
let shown = |h: &Headless| matches!(crate::panels::detail::view_overlay(&h.app, &develop(h)), Overlay::Mask { .. });
|
||||
hide(&mut h);
|
||||
exec(&mut h, "mask.add", json!({"kind": "radial", "center": [0.4, 0.5], "rx": 0.2, "ry": 0.2}));
|
||||
assert!(shown(&h), "a new mask shows its overlay");
|
||||
hide(&mut h);
|
||||
let r = h.request("ui.clickWidget", json!({"id": format!("mask:{first}")}), T);
|
||||
assert_eq!(r["ok"], true, "{r}");
|
||||
assert_eq!(h.app.session.active_mask, Some(first));
|
||||
assert!(shown(&h), "picking a mask in the list shows its overlay");
|
||||
for (cmd, params) in
|
||||
[("mask.addComponent", json!({"kind": "radial", "op": "add", "center": [0.6, 0.5], "rx": 0.1, "ry": 0.1})), ("mask.duplicate", json!({}))]
|
||||
{
|
||||
hide(&mut h);
|
||||
exec(&mut h, cmd, params);
|
||||
assert!(shown(&h), "{cmd} shows the overlay");
|
||||
}
|
||||
h.settle(SETTLE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn radial_body_drag_moves_rotated_components_and_undoes_once() {
|
||||
let mut h = detail("panel.masking");
|
||||
|
||||
@@ -310,7 +310,7 @@ differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts).
|
||||
| LR-MASK-FEATHER-EDGE | Refine mask edges | P2 | ✅ | `cmd:mask.refine`, `crates/pipeline/src/masks.rs` (`evaluate_one`) | Refine Edges slider per mask: guided filter on the photo's luminance snaps soft mask edges to the photo's edges (rendered on the CPU) |
|
||||
| LR-MASK-SLIDERS | Local adjustment sliders | P0 | ✅ | `cmd:mask.adjust`, `crates/pipeline/src/finish.rs` | every slider renders (CPU + GPU), incl. Noise, Moiré, Defringe (negative Defringe has no effect); no local curve |
|
||||
| LR-MASK-EFFECTS | Local adjustment (effect / brush) presets | P1 | ✅ | `cmd:mask.effects`, `cmd:mask.applyEffect`, `cmd:mask.saveEffect`, `cmd:mask.updateEffect`, `cmd:mask.renameEffect`, `cmd:mask.duplicateEffect`, `cmd:mask.deleteEffect`, `cmd:mask.favoriteEffect`, `cmd:mask.setEffectGroup`, `cmd:mask.renameEffectGroup`, `cmd:mask.toolEffect`, `cmd:mask.importEffects`, `cmd:mask.exportEffects`, `cmd:dialog.saveMaskEffect`, `cmd:dialog.manageMaskEffects`, `cmd:file.exportMaskEffects`, `crates/engine/src/cmd/mask_effects.rs`, `crates/engine/src/cmd/mask_effect_files.rs`, `crates/ui-egui/src/panels/mask_effects.rs` | Effect menu above the mask sliders: grouped (folders, ★ Favorites first), searchable, scrolls, ↑ ↓ Return, ✓ on the matching effect (else Custom), resting on an effect previews it on the photo; right-click: apply to all masks / to the same-named mask on the selected photos (one undo step), update, rename, duplicate, star, move to group, delete (asks first); Reset Sliders; New Effect Preset dialog: which sliders (All / None / Changed Only), Amount, brush size/feather/flow; any mask type; Manage Effect Presets window (search, inline rename, update, duplicate, stars, groups, export, delete with confirmation); a new mask starts with the effect last applied to a mask of its kind (per tool, kept with the library); imports Lightroom Classic local `.lrtemplate` presets, Camera Raw local-correction `.xmp` presets, `.lceffect` and `.zip` bundles, through File ▸ Import Profiles & Presets… and drag & drop too; folders and LrC divider presets (`10 ----- DETAIL ----- 10`) become groups; settings with no local slider here (`grain`, Point Color `pointColors`, `toningLuminance`) are reported and kept with the effect for export, not applied (🟡 for those); brush size/feather/flow aren't in LrC presets (it keeps them per brush), so only `.lceffect` carries them; no built-in effects |
|
||||
| LR-MASK-OVERLAY | Mask overlay | P0 | ✅ | `cmd:view.maskOverlay`, `cmd:view.maskOverlayMode`, `cmd:view.maskOverlayColor`, `crates/pipeline/src/visualize.rs` | rendered alpha of the selected mask (CPU + GPU): colour, colour on B&W, image on black/white, white on black; ⇧O cycles while masking; successful local adjustments (including Amount) hide the overlay until manually shown again with O / the eye; shape/edge edits retain it; zoomed in, the overlay is rendered on the same sharp window as the plain view (zoom and pan unchanged; `crates/ui-egui/src/tests_preview_limit.rs`, `crates/pipeline/src/tests_window.rs`); no auto-show on hover |
|
||||
| LR-MASK-OVERLAY | Mask overlay | P0 | ✅ | `cmd:view.maskOverlay`, `cmd:view.maskOverlayMode`, `cmd:view.maskOverlayColor`, `crates/pipeline/src/visualize.rs` | rendered alpha of the selected mask (CPU + GPU): colour, colour on B&W, image on black/white, white on black; ⇧O cycles while masking; successful local adjustments (including Amount) hide the overlay until O / the eye shows it again or a mask is created, picked, duplicated or added to (issue #1800); shape/edge edits retain it; zoomed in, the overlay is rendered on the same sharp window as the plain view (zoom and pan unchanged; `crates/ui-egui/src/tests_preview_limit.rs`, `crates/pipeline/src/tests_window.rs`); no auto-show on hover |
|
||||
| LR-MASK-OVERLAYALL | Show all mask overlays | P1 | ✅ | `cmd:view.maskOverlayAll`, `crates/ui-egui/src/panels/masking.rs`, `crates/pipeline/src/visualize.rs` | one diagnostic tint over every visible mask at once (CPU + GPU): the masks still stack their adjustments as before — this only paints each mask's region together, so you can see all masked areas at a glance (⌘⇧O / Ctrl+Shift+O) |
|
||||
| LR-MASK-PINS | Pins | P1 | ✅ | `cmd:view.maskPins`, `cmd:view.toolOverlay`, `crates/ui-egui/src/panels/detail.rs`, `crates/ui-egui/src/tests_tool_overlay.rs` | a pin per radial/linear/brush component: click selects its mask, drag moves it; Show Pins on follows the Tool Overlay mode (Auto: while the pointer is over the photo, hidden while brushing; Always; Selected: the selected mask's; Never; ⇧H cycles, #224); no pins for range/AI components |
|
||||
| LR-MASK-UPDATE | Recompute AI masks | P2 | ⬜ | | |
|
||||
@@ -801,6 +801,7 @@ Latin stays upright. Advanced Japanese composition remains open. Regression cove
|
||||
|---|---|---|
|
||||
| 2026-10-21 | patch | KEY-SLIDER-NUDGE: vertical wheel nudges need a click or drag in the slider's row; leaving it (even between two frames) or Tab focus alone does not arm them (issue #1355); status unchanged |
|
||||
| 2026-10-20 | minor | LR-PRE-PANEL: the preset applied to a photo is marked again (with its Amount slider) on returning to the photo, until the photo is edited further (#2392); status unchanged (✅) |
|
||||
| 2026-10-20 | minor | LR-MASK-OVERLAY: creating, picking, duplicating or adding to a mask shows the overlay a mask slider hid (#1800); status unchanged (✅) |
|
||||
| 2026-10-20 | patch | LR-VIEW-ZOOM: the 20 ms rule clears a slow-drag verdict only on a drag timed at full size; a drag that drafts small leaves it unchanged, as the code does; status unchanged |
|
||||
| 2026-10-19 | patch | LR-CROP-RECT: on a straightened photo a moved crop slides along the tilted edges, so a box that fills the photo's height reaches its sides (#2299); status unchanged |
|
||||
| 2026-10-19 | patch | LR-VIEW-ZOOM: the slow slider-drag verdict is described as per photo and control, as the code keys it; status unchanged |
|
||||
|
||||
Reference in New Issue
Block a user