fix(studio): a dust spot is a place on the photo, so a quarter turn carries it with the frame
This commit is contained in:
@@ -63,6 +63,7 @@ import {
|
||||
import { grainPerInch, grainStockFor } from '../shared/utils/grainShader';
|
||||
import { curveIsActive } from '../shared/utils/toneCurve';
|
||||
import { HEAL_DEFAULT_R } from '../shared/utils/heal';
|
||||
import { layMarks, type Orientation } from '../shared/utils/orientation';
|
||||
import { MOSAIC_DEFAULT_R } from '../shared/utils/mosaic';
|
||||
import { MASK_DEFAULT_FEATHER, MASK_EXPOSURE_MAX } from '../shared/utils/gradientMask';
|
||||
import { readHistogram, autoExposureStops, autoTone, autoWhiteBalance } from './ui/Histogram';
|
||||
@@ -1498,6 +1499,22 @@ export function Workspace() {
|
||||
[remember, setAdjustment]
|
||||
);
|
||||
|
||||
// The ROTATE strip and the two mirrors are the only things that move the photo
|
||||
// under the marks already on it, and a mark is a place on the photo, not a
|
||||
// place on the screen: turn the frame and every spot the dust brush laid down
|
||||
// has to turn with it, or the repair slides off its mote and the mote is
|
||||
// uncovered again (shared/utils/orientation.ts). One undo step, like the turn
|
||||
// itself — UNDO hands back the frame AND the marks of the frame before it.
|
||||
const carryMarks = useCallback(
|
||||
(next: Orientation) => {
|
||||
setRecipe((prev) => ({
|
||||
...prev,
|
||||
adjustments: layMarks(prev.adjustments, { rot: rotation, flipH, flipV }, next, photoDims),
|
||||
}));
|
||||
},
|
||||
[rotation, flipH, flipV, photoDims]
|
||||
);
|
||||
|
||||
// FX's HEAL brush writes the spots the same way a knob writes its value: one
|
||||
// gesture is one undo step whatever it laid down, so UNDO takes the dust back
|
||||
// out a stroke at a time, and CLEAR — one step — hands the whole photo back.
|
||||
@@ -2851,9 +2868,12 @@ export function Workspace() {
|
||||
],
|
||||
onPick: (v) => {
|
||||
remember();
|
||||
setRotation(v === 'reset' ? 0 : (Number(v) as 0 | 90 | 180 | 270));
|
||||
const next = v === 'reset' ? 0 : (Number(v) as 0 | 90 | 180 | 270);
|
||||
// RESET levels the whole frame, angle and mirrors included.
|
||||
if (v === 'reset') {
|
||||
const level = v === 'reset';
|
||||
carryMarks({ rot: next, flipH: level ? false : flipH, flipV: level ? false : flipV });
|
||||
setRotation(next);
|
||||
if (level) {
|
||||
setStraighten(0);
|
||||
setFlipH(false);
|
||||
setFlipV(false);
|
||||
@@ -3759,6 +3779,7 @@ export function Workspace() {
|
||||
active: flipH,
|
||||
onClick: () => {
|
||||
remember();
|
||||
carryMarks({ rot: rotation, flipH: !flipH, flipV });
|
||||
setFlipH((v) => !v);
|
||||
},
|
||||
},
|
||||
@@ -3768,6 +3789,7 @@ export function Workspace() {
|
||||
active: flipV,
|
||||
onClick: () => {
|
||||
remember();
|
||||
carryMarks({ rot: rotation, flipH, flipV: !flipV });
|
||||
setFlipV((v) => !v);
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user