feat: Unified Canvas Fit Image Size on Drop

This commit is contained in:
symant233 2024-04-04 18:41:22 +08:00 committed by psychedelicious
parent 4571986c63
commit 90686c7f9c
5 changed files with 26 additions and 6 deletions

View File

@ -1423,6 +1423,7 @@
"eraseBoundingBox": "Erase Bounding Box", "eraseBoundingBox": "Erase Bounding Box",
"eraser": "Eraser", "eraser": "Eraser",
"fillBoundingBox": "Fill Bounding Box", "fillBoundingBox": "Fill Bounding Box",
"initialFitImageSize": "Fit Image Size on Drop",
"invertBrushSizeScrollDirection": "Invert Scroll for Brush Size", "invertBrushSizeScrollDirection": "Invert Scroll for Brush Size",
"layer": "Layer", "layer": "Layer",
"limitStrokesToBox": "Limit Strokes to Box", "limitStrokesToBox": "Limit Strokes to Box",

View File

@ -584,6 +584,7 @@
"accept": "接受", "accept": "接受",
"discardAll": "放弃所有", "discardAll": "放弃所有",
"antialiasing": "抗锯齿", "antialiasing": "抗锯齿",
"initialFitImageSize": "初始适应图片大小",
"showResultsOn": "显示结果 (开)", "showResultsOn": "显示结果 (开)",
"showResultsOff": "显示结果 (关)", "showResultsOff": "显示结果 (关)",
"saveMask": "保存 $t(unifiedCanvas.mask)" "saveMask": "保存 $t(unifiedCanvas.mask)"

View File

@ -18,6 +18,7 @@ import {
setShouldAutoSave, setShouldAutoSave,
setShouldCropToBoundingBoxOnSave, setShouldCropToBoundingBoxOnSave,
setShouldDarkenOutsideBoundingBox, setShouldDarkenOutsideBoundingBox,
setShouldFitImageSize,
setShouldInvertBrushSizeScrollDirection, setShouldInvertBrushSizeScrollDirection,
setShouldRestrictStrokesToBox, setShouldRestrictStrokesToBox,
setShouldShowCanvasDebugInfo, setShouldShowCanvasDebugInfo,
@ -48,6 +49,7 @@ const IAICanvasSettingsButtonPopover = () => {
const shouldSnapToGrid = useAppSelector((s) => s.canvas.shouldSnapToGrid); const shouldSnapToGrid = useAppSelector((s) => s.canvas.shouldSnapToGrid);
const shouldRestrictStrokesToBox = useAppSelector((s) => s.canvas.shouldRestrictStrokesToBox); const shouldRestrictStrokesToBox = useAppSelector((s) => s.canvas.shouldRestrictStrokesToBox);
const shouldAntialias = useAppSelector((s) => s.canvas.shouldAntialias); const shouldAntialias = useAppSelector((s) => s.canvas.shouldAntialias);
const sholdFitImageSize = useAppSelector((s) => s.canvas.shouldFitImageSize);
useHotkeys( useHotkeys(
['n'], ['n'],
@ -102,6 +104,10 @@ const IAICanvasSettingsButtonPopover = () => {
(e: ChangeEvent<HTMLInputElement>) => dispatch(setShouldAntialias(e.target.checked)), (e: ChangeEvent<HTMLInputElement>) => dispatch(setShouldAntialias(e.target.checked)),
[dispatch] [dispatch]
); );
const handleChangeSholdFitImageSize = useCallback(
(e: ChangeEvent<HTMLInputElement>) => dispatch(setShouldFitImageSize(e.target.checked)),
[dispatch]
);
return ( return (
<Popover> <Popover>
@ -165,6 +171,10 @@ const IAICanvasSettingsButtonPopover = () => {
<FormLabel>{t('unifiedCanvas.antialiasing')}</FormLabel> <FormLabel>{t('unifiedCanvas.antialiasing')}</FormLabel>
<Checkbox isChecked={shouldAntialias} onChange={handleChangeShouldAntialias} /> <Checkbox isChecked={shouldAntialias} onChange={handleChangeShouldAntialias} />
</FormControl> </FormControl>
<FormControl>
<FormLabel>{t('unifiedCanvas.initialFitImageSize')}</FormLabel>
<Checkbox isChecked={sholdFitImageSize} onChange={handleChangeSholdFitImageSize} />
</FormControl>
</FormControlGroup> </FormControlGroup>
<ClearCanvasHistoryButtonModal /> <ClearCanvasHistoryButtonModal />
</Flex> </Flex>

View File

@ -66,6 +66,7 @@ const initialCanvasState: CanvasState = {
shouldAutoSave: false, shouldAutoSave: false,
shouldCropToBoundingBoxOnSave: false, shouldCropToBoundingBoxOnSave: false,
shouldDarkenOutsideBoundingBox: false, shouldDarkenOutsideBoundingBox: false,
shouldFitImageSize: false,
shouldInvertBrushSizeScrollDirection: false, shouldInvertBrushSizeScrollDirection: false,
shouldLockBoundingBox: false, shouldLockBoundingBox: false,
shouldPreserveMaskedArea: false, shouldPreserveMaskedArea: false,
@ -144,9 +145,11 @@ export const canvasSlice = createSlice({
reducer: (state, action: PayloadActionWithOptimalDimension<ImageDTO>) => { reducer: (state, action: PayloadActionWithOptimalDimension<ImageDTO>) => {
const { width, height, image_name } = action.payload; const { width, height, image_name } = action.payload;
const { optimalDimension } = action.meta; const { optimalDimension } = action.meta;
const { stageDimensions } = state; const { stageDimensions, shouldFitImageSize } = state;
const newBoundingBoxDimensions = { const newBoundingBoxDimensions = shouldFitImageSize
? { width, height }
: {
width: roundDownToMultiple(clamp(width, CANVAS_GRID_SIZE_FINE, optimalDimension), CANVAS_GRID_SIZE_FINE), width: roundDownToMultiple(clamp(width, CANVAS_GRID_SIZE_FINE, optimalDimension), CANVAS_GRID_SIZE_FINE),
height: roundDownToMultiple(clamp(height, CANVAS_GRID_SIZE_FINE, optimalDimension), CANVAS_GRID_SIZE_FINE), height: roundDownToMultiple(clamp(height, CANVAS_GRID_SIZE_FINE, optimalDimension), CANVAS_GRID_SIZE_FINE),
}; };
@ -582,6 +585,9 @@ export const canvasSlice = createSlice({
setShouldAntialias: (state, action: PayloadAction<boolean>) => { setShouldAntialias: (state, action: PayloadAction<boolean>) => {
state.shouldAntialias = action.payload; state.shouldAntialias = action.payload;
}, },
setShouldFitImageSize: (state, action: PayloadAction<boolean>) => {
state.shouldFitImageSize = action.payload;
},
setShouldCropToBoundingBoxOnSave: (state, action: PayloadAction<boolean>) => { setShouldCropToBoundingBoxOnSave: (state, action: PayloadAction<boolean>) => {
state.shouldCropToBoundingBoxOnSave = action.payload; state.shouldCropToBoundingBoxOnSave = action.payload;
}, },
@ -692,6 +698,7 @@ export const {
setShouldRestrictStrokesToBox, setShouldRestrictStrokesToBox,
stagingAreaInitialized, stagingAreaInitialized,
setShouldAntialias, setShouldAntialias,
setShouldFitImageSize,
canvasResized, canvasResized,
canvasBatchIdAdded, canvasBatchIdAdded,
canvasBatchIdsReset, canvasBatchIdsReset,

View File

@ -120,6 +120,7 @@ export interface CanvasState {
shouldAutoSave: boolean; shouldAutoSave: boolean;
shouldCropToBoundingBoxOnSave: boolean; shouldCropToBoundingBoxOnSave: boolean;
shouldDarkenOutsideBoundingBox: boolean; shouldDarkenOutsideBoundingBox: boolean;
shouldFitImageSize: boolean;
shouldInvertBrushSizeScrollDirection: boolean; shouldInvertBrushSizeScrollDirection: boolean;
shouldLockBoundingBox: boolean; shouldLockBoundingBox: boolean;
shouldPreserveMaskedArea: boolean; shouldPreserveMaskedArea: boolean;