Commit Graph
15 Commits
Author SHA1 Message Date
aiongg e42cfd2159 Merge PR #7574: Move tool: moving selected pixels shrinks the selection, transform controls and snapping to them (#7538)
crates/engine/src/float_cmds.rs: kept main's cut_piece (parallel, shares full tiles) and try_lift_coverage, and the PR's CutParts::outline; the outline is read from the piece's alpha, which holds min(alpha, selection) as the PR's own lift loop computed, instead of replacing cut_piece with that loop.
crates/engine/src/float_cmds/tests.rs: git interleaved the two sides' new tests; took main's file and appended the PR's added tests whole.
docs/ui-parity.md: header line keeps main's text plus the PR's #7538 item.
2026-10-22 02:26:55 +00:00
aiongg f32f882f3a Merge main into integration-10
# Conflicts:
#	apps/photocraft-web/src/web.rs
#	apps/photocraft/src/services.rs
#	crates/engine/src/file_cmds/tests.rs
#	crates/engine/src/float_cmds.rs
#	crates/engine/src/float_cmds/tests.rs
#	xtask/src/corpus.rs
#	xtask/src/corpus_pins.rs
#	xtask/src/main.rs
2026-10-21 21:56:26 +00:00
aiongg 38f684e4e4 Merge PR #7661: Move tool: a selection lifts up to a pixel's own coverage (#7655) 2026-10-21 21:55:49 +00:00
skylar taylor-barrickandGitHub 18e2d45420 Merge pull request #6318 from robertoffmoura/fix/floating-selection-move-lag
Fix lag when dragging a floating selection with the Move tool
2026-10-21 14:25:55 -06:00
Roberto Moura 8352b26c1a Fix lag when dragging a floating selection with the Move tool
- Replace whole-region Vec<f32> read_region/write_region in CutParts::new
  with tile-parallel cut_piece + try_fill_surface/try_clear_surface,
  sharing interior Arc<Tile> allocations in O(1) and activating the
  solid_tile hole-fill fast path on Background and mask targets.
- Cache piece_bounds on CutParts so CutParts::place avoids scanning tile
  content bounds on every drag frame.
- Parallelize composite_over across top tiles with Rayon and share fully
  opaque top tiles by Arc<Tile> clone in O(1), preserving COW tile
  identity for GPU canvas uploads.
- Parallelize Surface::translated across target tiles with Rayon and
  prune cleared tiles in-place inside edit_tiles.
- Skip zero-offset floating preview generation on pointer-down in
  move_ui::floating_doc.
- Exclude SnapKind::Selection when moving selected pixels with the Move
  tool so small initial drags do not snap back to (0, 0).
- Keep navigator_plain active during Move/Brush/Patch drags on a GPU
  canvas so navigator_gpu is not evicted into a synchronous full-document
  CPU thumbnail composite on the first drag frame.
- Parallelize row normalization in compose::render_reduced_in_bands and
  add a direct read_rgba_into fast path for unmasked Normal layers over
  an empty backdrop.
2026-10-21 13:21:10 +00:00
Hector VillarrealandClaude Opus 5.5 9e22dda917 Test: a copy floated by the layer's own transparency is as solid as the original
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:26:36 -06:00
Hector VillarrealandClaude Opus 5.5 c1f20c239d Move tool: a selection lifts up to a pixel's own coverage (#7655)
Loading a layer's transparency as the selection and dragging it with the Move
tool left a ghost of a·(1−a). Photoshop lifts the selection's share of a
pixel's coverage, up to all of it, and leaves the rest, so its own
transparency lifts it whole. Opaque pixels split as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:07:47 -06:00
Hector VillarrealandClaude Opus 5.5 afa8706139 Move tool: soft edges stay partly selected and move whole, as in Photoshop (#7538)
Checked against Photoshop 2025 on a 15 px feathered shape moved from a loose
marquee:

- Its selection after the move follows the edge's transparency: the marching
  ants run along the 50 % line and Quick Mask shows the edge partly selected
  (measured strength 0.10 / 0.29 / 0.42 / 0.64 / 0.81 where alpha is 0.05 /
  0.24 / 0.39 / 0.57 / 0.71). We had made those pixels fully selected.
- Moving it again, even after Deselect and Reselect, leaves nothing behind,
  though Delete with the same selection leaves a ghost: the Move tool lifts at
  most each pixel's alpha, not alpha × selection.

So the move cut lifts min(alpha, selection) of each pixel (feathered moves over
opaque pixels are unchanged: k lifted, 1 − k left), and the moved pixels'
selection is what they took. Moving them again lifts them whole, with no faint
outline, and their ants hug the soft edge's 50 % line.

Also: arrow nudges add up to one floating piece, so up then down was back at
no offset and the drop kept the loose marquee. A piece that moved and came back
now keeps the moved pixels' selection, in one step; a click still changes
nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:56:41 -06:00
Hector VillarrealandClaude Opus 5.5 cb85f77f5a Move tool: moving pixels again leaves no faint outline behind (#7538)
The shrunk selection took the moved pixels' alpha as its coverage, so
anti-aliased edges were only partly selected. Once the move was dropped
(changing layers, say), moving them again lifted a × a of each edge pixel and
left a × (1 − a) behind: up to 25 %, a faint outline where the shape had been.

The selection now keeps its own strength wherever the layer has pixels, so a
later move lifts edge pixels whole. Tested at 8, 16 and 32 bit: nothing is left
behind and the shape's total alpha is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:20:43 -06:00
Hector VillarrealandClaude Opus 5.5 987753e76e Move tool: moving selected pixels shrinks the selection to them, as in Photoshop (#7538)
A marquee drawn loosely around an object on a transparent layer kept its
rectangle when the Move tool dragged the pixels. Photoshop shrinks the
marching ants to the pixels being moved as the drag starts: the selection
times the layer's transparency.

- Engine: the floating piece keeps its outline (`CutParts::outline`, the
  piece's alpha), and `select.drop` makes it the new selection. A mask,
  which has no transparency, and an empty piece keep the selection's shape.
- Canvas: a floating piece's ants follow that outline during the drag.
- Snapping and the move box use the moved pixels' bounds.

Tests at 8, 16 and 32 bit, Alt-drag copies, soft selections over
half-transparent pixels, the Background, a mask target and an empty piece.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:20:43 -06:00
David MannandClaude Opus 5.5 e23840f516 History panel menu: review fixes (floating steps, cleared-state memory, clean undo, New Snapshot)
- Step Backward in the History panel puts a floating selection back like Edit > Undo; Step
  Forward and Edit > Redo put it back and step instead of dropping it first (which recorded a
  Move and wiped the redo states); with nothing to step to the piece keeps floating.
- Memory figures and the byte budget count the states Clear History keeps for its undo.
- Undoing Clear History keeps a saved document clean.
- New Snapshot... in the panel menu runs history.newSnapshot.
- Tests: Clear on one document leaves the others alone, and each fix above.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 13:57:54 +02:00
MarekSpodBiedryandGitHub 93629daedc Float the layer mask, not the layer, when the mask is targeted (#2468) (#2486) 2026-10-10 13:12:20 -04:00
7238b4100d Move tool moves the selected pixels when there is a selection (#578) (#1068)
* Move tool moves the selected pixels when there is a selection (#578)

With a selection, a Move-tool drag (from anywhere) or arrow-key nudge now
floats the active layer's selected pixels (select.float) instead of moving
the whole layer: the hole is transparent, or the background colour on the
Background layer; Alt copies the pixels instead of duplicating the layer;
Shift constrains the drag to 45 degrees; Enter, Deselect or any other
command drops the piece as one "Move" history step. Layers whose pixels
can't float (type, shape, smart object, group, position-locked, hidden, or
several selected layers) and Auto-Select without a selection behave as
before. select.float gains "copy"; a click that moves nothing no longer
leaves a floating piece behind.

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

* Pipette cursor test: Windows draws the precise crosshair itself

input_tests::eyedropper_and_alt_sampling_show_a_pipette (#1028) expected
the OS crosshair with Other Cursors = Precise, but on Windows the canvas
draws its own crosshair and hides the OS cursor (visible_crosshair), so
the test failed on every Windows run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UHgFEHEsefoQoBParH47JA

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:37:57 +07:00
26b6aac9ac Selection tools: ⌘ moves like the Move tool; ⌘⌥ copies (pixels inside the selection, the layer outside) (#896)
* Selection drags: ⌘⌥-drag floats a copy; ⌘-drag with the Polygonal Lasso and Magic Wand

- `select.float {"copy": true}` floats a duplicate of the selected pixels
  and leaves the originals in the layer; ⌘⌥-drag inside the selection uses
  it (⌘-drag still cuts).
- ⌘-drag inside the selection now also floats it with the Polygonal Lasso
  and the Magic Wand (not while a polygon is being drawn); a plain press
  there still places a point / samples, so only ⌘ moves the selection.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ⌘ / ⌘⌥ with a selection always cut / copy and drag it, never combine selections

With a selection tool and an active selection, a ⌘ or ⌘⌥ press anywhere (not
only inside the ants) floats the selected pixels (cut, or copy with ⌥) and
drags them; ⌥ no longer turns it into a subtract. The cursor shows no
selection-mode badge while ⌘ is held over a selection.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ⌘ with a selection tool moves the layer outside the selection; ⌘⌥ duplicates it

With a selection tool, ⌘ acts as the Move tool for the drag: inside the
selection it cuts the selected pixels (⌘⌥ copies them), and outside the
selection, or without one, it moves the whole layer; ⌘⌥ duplicates the
layer first and moves the copy. ⌘ never combines selections, so the cursor
shows no add / subtract badge while it is held.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ⌘ outside the selection moves the layer, not the selected pixels

Only a ⌘ press inside the selection floats its pixels; outside it the layer
moves (`command_moves_layer`). Drops the duplicate badge check.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ⌘⌥-drag on a floating piece drops it and drags a copy

A floating piece (from a ⌘ cut-drag) dragged again with ⌘⌥ is dropped where
it is and a copy of it floats with the pointer, as ⌘⌥ does on any selection.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jason Short <3344856+jason4short@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 16:09:00 -04:00
6c7d01a0f3 Selections: drag to move the outline; ⌘-drag floats the selected pixels (engine commands) (#686)
Engine (scripts, the control channel and agents can drive it):
- `select.float {"dx","dy"}`: cuts the selected pixels of the active layer
  into a floating piece the first time, then moves it by whole pixels.
  The document is unchanged while it floats (`DocState::floating`);
  `float_cmds::displayed` gives the document with the piece at its offset.
- `select.drop`: drops the piece into its layer and moves the selection
  with it, one history step ("Move Selected Pixels").
- Any other command drops a floating piece first (a hook at the top of
  dispatch, so it lands where it was shown); Undo puts it back instead.
- The layer is split once, only inside the selection, and the piece is
  cropped to it: placing it costs the piece, not the layer (6000×4000
  layer, 500×400 piece: 18 ms to cut, under 5 ms per move).

Canvas (Marquee / Lasso):
- A drag inside the ants moves the outline (`select.transformSelection`);
  a click inside without moving deselects; ⇧ / ⌥ drags still draw.
- ⌘-drag floats the selected pixels and shows them at the pointer live;
  plain drags on the piece move it again; a press elsewhere drops it.
- A move cursor over the ants; the ants follow the dragged / floating piece.

Co-authored-by: Jason Short <3344856+jason4short@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-07 16:45:31 -04:00