feat(ui): move canvas tool to nanostores

I was troubleshooting a hotkeys issue on canvas and thought I had broken the tool logic in a past change so I redid it moving it to nanostores. In the end, the issue was an upstream but with the hotkeys library, but I like having tool in nanostores so I'm leaving it.

It's ephemeral interaction state anyways, doesn't need to be in redux.
This commit is contained in:
psychedelicious 2024-01-09 18:13:38 +11:00 committed by Kent Keirsey
parent b501bd709f
commit 21ab650ac0
13 changed files with 144 additions and 160 deletions

View File

@ -14,6 +14,7 @@ import {
$isMouseOverBoundingBox,
$isMovingStage,
$isTransformingBoundingBox,
$tool,
} from 'features/canvas/store/canvasNanostore';
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
import {
@ -61,7 +62,6 @@ const IAICanvas = () => {
);
const shouldShowGrid = useAppSelector((s) => s.canvas.shouldShowGrid);
const stageScale = useAppSelector((s) => s.canvas.stageScale);
const tool = useAppSelector((s) => s.canvas.tool);
const shouldShowIntermediates = useAppSelector(
(s) => s.canvas.shouldShowIntermediates
);
@ -78,6 +78,7 @@ const IAICanvas = () => {
const isMovingStage = useStore($isMovingStage);
const isTransformingBoundingBox = useStore($isTransformingBoundingBox);
const isMouseOverBoundingBox = useStore($isMouseOverBoundingBox);
const tool = useStore($tool);
useCanvasHotkeys();
const canvasStageRefCallback = useCallback((el: Konva.Stage) => {
setCanvasStage(el as Konva.Stage);

View File

@ -8,11 +8,11 @@ import {
} from 'common/util/roundDownToMultiple';
import {
$isDrawing,
$isMouseOverBoundingBox,
$isMouseOverBoundingBoxOutline,
$isMovingBoundingBox,
$isTransformingBoundingBox,
setIsMouseOverBoundingBox,
setIsMovingBoundingBox,
setIsTransformingBoundingBox,
$tool,
} from 'features/canvas/store/canvasNanostore';
import {
aspectRatioChanged,
@ -30,7 +30,7 @@ import type Konva from 'konva';
import type { GroupConfig } from 'konva/lib/Group';
import type { KonvaEventObject } from 'konva/lib/Node';
import type { Vector2d } from 'konva/lib/types';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { Group, Rect, Transformer } from 'react-konva';
@ -49,18 +49,19 @@ const IAICanvasBoundingBox = (props: IAICanvasBoundingBoxPreviewProps) => {
);
const stageScale = useAppSelector((s) => s.canvas.stageScale);
const shouldSnapToGrid = useAppSelector((s) => s.canvas.shouldSnapToGrid);
const tool = useAppSelector((s) => s.canvas.tool);
const hitStrokeWidth = useAppSelector((s) => 20 / s.canvas.stageScale);
const aspectRatio = useAppSelector((s) => s.canvas.aspectRatio);
const optimalDimension = useAppSelector(selectOptimalDimension);
const transformerRef = useRef<Konva.Transformer>(null);
const shapeRef = useRef<Konva.Rect>(null);
const shift = useStore($shift);
const tool = useStore($tool);
const isDrawing = useStore($isDrawing);
const isMovingBoundingBox = useStore($isMovingBoundingBox);
const isTransformingBoundingBox = useStore($isTransformingBoundingBox);
const [isMouseOverBoundingBoxOutline, setIsMouseOverBoundingBoxOutline] =
useState(false);
const isMouseOverBoundingBoxOutline = useStore(
$isMouseOverBoundingBoxOutline
);
useEffect(() => {
if (!transformerRef.current || !shapeRef.current) {
@ -228,43 +229,43 @@ const IAICanvasBoundingBox = (props: IAICanvasBoundingBoxPreviewProps) => {
);
const handleStartedTransforming = useCallback(() => {
setIsTransformingBoundingBox(true);
$isTransformingBoundingBox.set(true);
}, []);
const handleEndedTransforming = useCallback(() => {
setIsTransformingBoundingBox(false);
setIsMovingBoundingBox(false);
setIsMouseOverBoundingBox(false);
setIsMouseOverBoundingBoxOutline(false);
$isTransformingBoundingBox.set(false);
$isMovingBoundingBox.set(false);
$isMouseOverBoundingBox.set(false);
$isMouseOverBoundingBoxOutline.set(false);
}, []);
const handleStartedMoving = useCallback(() => {
setIsMovingBoundingBox(true);
$isMovingBoundingBox.set(true);
}, []);
const handleEndedModifying = useCallback(() => {
setIsTransformingBoundingBox(false);
setIsMovingBoundingBox(false);
setIsMouseOverBoundingBox(false);
setIsMouseOverBoundingBoxOutline(false);
$isTransformingBoundingBox.set(false);
$isMovingBoundingBox.set(false);
$isMouseOverBoundingBox.set(false);
$isMouseOverBoundingBoxOutline.set(false);
}, []);
const handleMouseOver = useCallback(() => {
setIsMouseOverBoundingBoxOutline(true);
$isMouseOverBoundingBoxOutline.set(true);
}, []);
const handleMouseOut = useCallback(() => {
!isTransformingBoundingBox &&
!isMovingBoundingBox &&
setIsMouseOverBoundingBoxOutline(false);
$isMouseOverBoundingBoxOutline.set(false);
}, [isMovingBoundingBox, isTransformingBoundingBox]);
const handleMouseEnterBoundingBox = useCallback(() => {
setIsMouseOverBoundingBox(true);
$isMouseOverBoundingBox.set(true);
}, []);
const handleMouseLeaveBoundingBox = useCallback(() => {
setIsMouseOverBoundingBox(false);
$isMouseOverBoundingBox.set(false);
}, []);
const stroke = useMemo(() => {

View File

@ -1,4 +1,5 @@
import { Box, Flex } from '@chakra-ui/react';
import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIColorPicker from 'common/components/IAIColorPicker';
import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup';
@ -10,14 +11,16 @@ import {
InvPopoverTrigger,
} from 'common/components/InvPopover/wrapper';
import { InvSlider } from 'common/components/InvSlider/InvSlider';
import { resetToolInteractionState } from 'features/canvas/store/canvasNanostore';
import {
$tool,
resetToolInteractionState,
} from 'features/canvas/store/canvasNanostore';
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
import {
addEraseRect,
addFillRect,
setBrushColor,
setBrushSize,
setTool,
} from 'features/canvas/store/canvasSlice';
import { InvIconButton, InvPopover } from 'index';
import { clamp } from 'lodash-es';
@ -34,9 +37,11 @@ import {
PiXBold,
} from 'react-icons/pi';
const marks = [1, 25, 50, 75, 100];
const IAICanvasToolChooserOptions = () => {
const dispatch = useAppDispatch();
const tool = useAppSelector((s) => s.canvas.tool);
const tool = useStore($tool);
const brushColor = useAppSelector((s) => s.canvas.brushColor);
const brushSize = useAppSelector((s) => s.canvas.brushSize);
const isStaging = useAppSelector(isStagingSelector);
@ -163,17 +168,17 @@ const IAICanvasToolChooserOptions = () => {
);
const handleSelectBrushTool = useCallback(() => {
dispatch(setTool('brush'));
$tool.set('brush');
resetToolInteractionState();
}, [dispatch]);
}, []);
const handleSelectEraserTool = useCallback(() => {
dispatch(setTool('eraser'));
$tool.set('eraser');
resetToolInteractionState();
}, [dispatch]);
}, []);
const handleSelectColorPickerTool = useCallback(() => {
dispatch(setTool('colorPicker'));
$tool.set('colorPicker');
resetToolInteractionState();
}, [dispatch]);
}, []);
const handleFillRect = useCallback(() => {
dispatch(addFillRect());
}, [dispatch]);
@ -281,5 +286,3 @@ const IAICanvasToolChooserOptions = () => {
};
export default memo(IAICanvasToolChooserOptions);
const marks = [1, 25, 50, 75, 100];

View File

@ -1,4 +1,5 @@
import { Flex } from '@chakra-ui/react';
import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup';
import { InvControl } from 'common/components/InvControl/InvControl';
@ -14,13 +15,13 @@ import {
canvasMerged,
canvasSavedToGallery,
} from 'features/canvas/store/actions';
import { $tool } from 'features/canvas/store/canvasNanostore';
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
import {
resetCanvas,
resetCanvasView,
setIsMaskEnabled,
setLayer,
setTool,
} from 'features/canvas/store/canvasSlice';
import type { CanvasLayer } from 'features/canvas/store/canvasTypes';
import { LAYER_NAMES_DICT } from 'features/canvas/store/canvasTypes';
@ -50,7 +51,7 @@ const IAICanvasToolbar = () => {
const dispatch = useAppDispatch();
const isMaskEnabled = useAppSelector((s) => s.canvas.isMaskEnabled);
const layer = useAppSelector((s) => s.canvas.layer);
const tool = useAppSelector((s) => s.canvas.tool);
const tool = useStore($tool);
const isStaging = useAppSelector(isStagingSelector);
const canvasBaseLayer = getCanvasBaseLayer();
const { t } = useTranslation();
@ -133,8 +134,8 @@ const IAICanvasToolbar = () => {
);
const handleSelectMoveTool = useCallback(() => {
dispatch(setTool('move'));
}, [dispatch]);
$tool.set('move');
}, []);
const handleClickResetCanvasView = useSingleAndDoubleClick(
() => handleResetCanvasView(false),

View File

@ -1,8 +1,8 @@
import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import {
$isMovingBoundingBox,
setIsMovingStage,
$isMovingStage,
$tool,
} from 'features/canvas/store/canvasNanostore';
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
import { setStageCoordinates } from 'features/canvas/store/canvasSlice';
@ -12,18 +12,19 @@ import { useCallback } from 'react';
const useCanvasDrag = () => {
const dispatch = useAppDispatch();
const isStaging = useAppSelector(isStagingSelector);
const tool = useAppSelector((s) => s.canvas.tool);
const isMovingBoundingBox = useStore($isMovingBoundingBox);
const handleDragStart = useCallback(() => {
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
if (
!(($tool.get() === 'move' || isStaging) && !$isMovingBoundingBox.get())
) {
return;
}
setIsMovingStage(true);
}, [isMovingBoundingBox, isStaging, tool]);
$isMovingStage.set(true);
}, [isStaging]);
const handleDragMove = useCallback(
(e: KonvaEventObject<MouseEvent>) => {
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
const tool = $tool.get();
if (!((tool === 'move' || isStaging) && !$isMovingBoundingBox.get())) {
return;
}
@ -31,15 +32,17 @@ const useCanvasDrag = () => {
dispatch(setStageCoordinates(newCoordinates));
},
[dispatch, isMovingBoundingBox, isStaging, tool]
[dispatch, isStaging]
);
const handleDragEnd = useCallback(() => {
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
if (
!(($tool.get() === 'move' || isStaging) && !$isMovingBoundingBox.get())
) {
return;
}
setIsMovingStage(false);
}, [isMovingBoundingBox, isStaging, tool]);
$isMovingStage.set(false);
}, [isStaging]);
return {
handleDragStart,

View File

@ -1,5 +1,7 @@
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import {
$tool,
$toolStash,
resetCanvasInteractionState,
resetToolInteractionState,
} from 'features/canvas/store/canvasNanostore';
@ -9,12 +11,10 @@ import {
setIsMaskEnabled,
setShouldShowBoundingBox,
setShouldSnapToGrid,
setTool,
} from 'features/canvas/store/canvasSlice';
import type { CanvasTool } from 'features/canvas/store/canvasTypes';
import { getCanvasStage } from 'features/canvas/util/konvaInstanceProvider';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { useCallback, useRef } from 'react';
import { useCallback, useEffect } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
const useInpaintingCanvasHotkeys = () => {
@ -23,11 +23,9 @@ const useInpaintingCanvasHotkeys = () => {
const shouldShowBoundingBox = useAppSelector(
(s) => s.canvas.shouldShowBoundingBox
);
const tool = useAppSelector((s) => s.canvas.tool);
const isStaging = useAppSelector(isStagingSelector);
const isMaskEnabled = useAppSelector((s) => s.canvas.isMaskEnabled);
const shouldSnapToGrid = useAppSelector((s) => s.canvas.shouldSnapToGrid);
const previousToolRef = useRef<CanvasTool | null>(null);
const canvasStage = getCanvasStage();
// Beta Keys
@ -96,37 +94,53 @@ const useInpaintingCanvasHotkeys = () => {
[activeTabName, shouldShowBoundingBox]
);
useHotkeys(
['space'],
useEffect(() => {
window.addEventListener('keydown', (e) => {
if (e.key === ' ' && !e.repeat) {
console.log('spaceeee');
}
});
}, []);
const onKeyDown = useCallback(
(e: KeyboardEvent) => {
if (e.repeat) {
if (e.repeat || e.key !== ' ') {
return;
}
if ($toolStash.get() || $tool.get() === 'move') {
return;
}
canvasStage?.container().focus();
if (tool !== 'move') {
previousToolRef.current = tool;
dispatch(setTool('move'));
$toolStash.set($tool.get());
$tool.set('move');
resetToolInteractionState();
}
if (
tool === 'move' &&
previousToolRef.current &&
previousToolRef.current !== 'move'
) {
dispatch(setTool(previousToolRef.current));
previousToolRef.current = 'move';
}
},
{
keyup: true,
keydown: true,
preventDefault: true,
},
[tool, previousToolRef]
[canvasStage]
);
const onKeyUp = useCallback(
(e: KeyboardEvent) => {
if (e.repeat || e.key !== ' ') {
return;
}
if (!$toolStash.get() || $tool.get() !== 'move') {
return;
}
canvasStage?.container().focus();
$tool.set($toolStash.get() ?? 'move');
$toolStash.set(null);
},
[canvasStage]
);
useEffect(() => {
window.addEventListener('keydown', onKeyDown);
window.addEventListener('keyup', onKeyUp);
return () => {
window.removeEventListener('keydown', onKeyDown);
window.removeEventListener('keyup', onKeyUp);
};
}, [onKeyDown, onKeyUp]);
};
export default useInpaintingCanvasHotkeys;

View File

@ -1,7 +1,8 @@
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import {
setIsDrawing,
setIsMovingStage,
$isDrawing,
$isMovingStage,
$tool,
} from 'features/canvas/store/canvasNanostore';
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
import { addLine } from 'features/canvas/store/canvasSlice';
@ -15,7 +16,6 @@ import useColorPicker from './useColorUnderCursor';
const useCanvasMouseDown = (stageRef: MutableRefObject<Konva.Stage | null>) => {
const dispatch = useAppDispatch();
const tool = useAppSelector((s) => s.canvas.tool);
const isStaging = useAppSelector(isStagingSelector);
const { commitColorUnderCursor } = useColorPicker();
@ -26,9 +26,10 @@ const useCanvasMouseDown = (stageRef: MutableRefObject<Konva.Stage | null>) => {
}
stageRef.current.container().focus();
const tool = $tool.get();
if (tool === 'move' || isStaging) {
setIsMovingStage(true);
$isMovingStage.set(true);
return;
}
@ -45,12 +46,17 @@ const useCanvasMouseDown = (stageRef: MutableRefObject<Konva.Stage | null>) => {
e.evt.preventDefault();
setIsDrawing(true);
$isDrawing.set(true);
// Add a new line starting from the current cursor position.
dispatch(addLine([scaledCursorPosition.x, scaledCursorPosition.y]));
dispatch(
addLine({
points: [scaledCursorPosition.x, scaledCursorPosition.y],
tool,
})
);
},
[stageRef, tool, isStaging, dispatch, commitColorUnderCursor]
[stageRef, isStaging, dispatch, commitColorUnderCursor]
);
};

View File

@ -1,8 +1,8 @@
import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import {
$cursorPosition,
$isDrawing,
setCursorPosition,
$tool,
} from 'features/canvas/store/canvasNanostore';
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
import { addPointToCurrentLine } from 'features/canvas/store/canvasSlice';
@ -20,8 +20,6 @@ const useCanvasMouseMove = (
lastCursorPositionRef: MutableRefObject<Vector2d>
) => {
const dispatch = useAppDispatch();
const isDrawing = useStore($isDrawing);
const tool = useAppSelector((s) => s.canvas.tool);
const isStaging = useAppSelector(isStagingSelector);
const { updateColorUnderCursor } = useColorPicker();
@ -36,16 +34,17 @@ const useCanvasMouseMove = (
return;
}
setCursorPosition(scaledCursorPosition);
$cursorPosition.set(scaledCursorPosition);
lastCursorPositionRef.current = scaledCursorPosition;
const tool = $tool.get();
if (tool === 'colorPicker') {
updateColorUnderCursor();
return;
}
if (!isDrawing || tool === 'move' || isStaging) {
if (!$isDrawing.get() || tool === 'move' || isStaging) {
return;
}
@ -56,11 +55,9 @@ const useCanvasMouseMove = (
}, [
didMouseMoveRef,
dispatch,
isDrawing,
isStaging,
lastCursorPositionRef,
stageRef,
tool,
updateColorUnderCursor,
]);
};

View File

@ -2,8 +2,8 @@ import { useStore } from '@nanostores/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import {
$isDrawing,
setIsDrawing,
setIsMovingStage,
$isMovingStage,
$tool,
} from 'features/canvas/store/canvasNanostore';
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
import { addPointToCurrentLine } from 'features/canvas/store/canvasSlice';
@ -18,12 +18,11 @@ const useCanvasMouseUp = (
) => {
const dispatch = useAppDispatch();
const isDrawing = useStore($isDrawing);
const tool = useAppSelector((s) => s.canvas.tool);
const isStaging = useAppSelector(isStagingSelector);
return useCallback(() => {
if (tool === 'move' || isStaging) {
setIsMovingStage(false);
if ($tool.get() === 'move' || isStaging) {
$isMovingStage.set(false);
return;
}
@ -46,8 +45,8 @@ const useCanvasMouseUp = (
} else {
didMouseMoveRef.current = false;
}
setIsDrawing(false);
}, [didMouseMoveRef, dispatch, isDrawing, isStaging, stageRef, tool]);
$isDrawing.set(false);
}, [didMouseMoveRef, dispatch, isDrawing, isStaging, stageRef]);
};
export default useCanvasMouseUp;

View File

@ -1,4 +1,5 @@
import { useAppDispatch } from 'app/store/storeHooks';
import { $tool } from 'features/canvas/store/canvasNanostore';
import {
commitColorPickerColor,
setColorPickerColor,
@ -51,6 +52,7 @@ const useColorPicker = () => {
const commitColorUnderCursor = useCallback(() => {
dispatch(commitColorPickerColor());
$tool.set('brush')
}, [dispatch]);
return { updateColorUnderCursor, commitColorUnderCursor };

View File

@ -1,7 +1,10 @@
import type { CanvasTool } from 'features/canvas/store/canvasTypes';
import type { Vector2d } from 'konva/lib/types';
import { atom, computed } from 'nanostores';
export const $cursorPosition = atom<Vector2d | null>(null);
export const $tool = atom<CanvasTool>('move');
export const $toolStash = atom<CanvasTool | null>(null);
export const $isDrawing = atom<boolean>(false);
export const $isMouseOverBoundingBox = atom<boolean>(false);
export const $isMoveBoundingBoxKeyHeld = atom<boolean>(false);
@ -9,6 +12,7 @@ export const $isMoveStageKeyHeld = atom<boolean>(false);
export const $isMovingBoundingBox = atom<boolean>(false);
export const $isMovingStage = atom<boolean>(false);
export const $isTransformingBoundingBox = atom<boolean>(false);
export const $isMouseOverBoundingBoxOutline = atom<boolean>(false);
export const $isModifyingBoundingBox = computed(
[$isTransformingBoundingBox, $isMovingBoundingBox],
(isTransformingBoundingBox, isMovingBoundingBox) =>
@ -25,49 +29,13 @@ export const resetCanvasInteractionState = () => {
$isMovingStage.set(false);
};
export const setCursorPosition = (cursorPosition: Vector2d | null) => {
$cursorPosition.set(cursorPosition);
};
export const setIsDrawing = (isDrawing: boolean) => {
$isDrawing.set(isDrawing);
};
export const setIsMouseOverBoundingBox = (isMouseOverBoundingBox: boolean) => {
$isMouseOverBoundingBox.set(isMouseOverBoundingBox);
};
export const setIsMoveBoundingBoxKeyHeld = (
isMoveBoundingBoxKeyHeld: boolean
) => {
$isMoveBoundingBoxKeyHeld.set(isMoveBoundingBoxKeyHeld);
};
export const setIsMoveStageKeyHeld = (isMoveStageKeyHeld: boolean) => {
$isMoveStageKeyHeld.set(isMoveStageKeyHeld);
};
export const setIsMovingBoundingBox = (isMovingBoundingBox: boolean) => {
$isMovingBoundingBox.set(isMovingBoundingBox);
};
export const setIsMovingStage = (isMovingStage: boolean) => {
$isMovingStage.set(isMovingStage);
};
export const setIsTransformingBoundingBox = (
isTransformingBoundingBox: boolean
) => {
$isTransformingBoundingBox.set(isTransformingBoundingBox);
};
export const resetToolInteractionState = () => {
setIsTransformingBoundingBox(false);
setIsMouseOverBoundingBox(false);
setIsMovingBoundingBox(false);
setIsMovingStage(false);
$isTransformingBoundingBox.set(false);
$isMouseOverBoundingBox.set(false);
$isMovingBoundingBox.set(false);
$isMovingStage.set(false);
};
export const setCanvasInteractionStateMouseOut = () => {
setCursorPosition(null);
$cursorPosition.set(null);
};

View File

@ -10,7 +10,6 @@ import calculateScale from 'features/canvas/util/calculateScale';
import { STAGE_PADDING_PERCENTAGE } from 'features/canvas/util/constants';
import floorCoordinates from 'features/canvas/util/floorCoordinates';
import getScaledBoundingBoxDimensions from 'features/canvas/util/getScaledBoundingBoxDimensions';
import roundDimensionsToMultiple from 'features/canvas/util/roundDimensionsToMultiple';
import { initialAspectRatioState } from 'features/parameters/components/ImageSize/constants';
import type { AspectRatioState } from 'features/parameters/components/ImageSize/types';
import { modelChanged } from 'features/parameters/store/generationSlice';
@ -86,7 +85,6 @@ export const initialCanvasState: CanvasState = {
stageCoordinates: { x: 0, y: 0 },
stageDimensions: { width: 0, height: 0 },
stageScale: 1,
tool: 'brush',
batchIds: [],
aspectRatio: {
id: '1:1',
@ -119,18 +117,9 @@ export const canvasSlice = createSlice({
name: 'canvas',
initialState: initialCanvasState,
reducers: {
setTool: (state, action: PayloadAction<CanvasTool>) => {
state.tool = action.payload;
},
setLayer: (state, action: PayloadAction<CanvasLayer>) => {
state.layer = action.payload;
},
toggleTool: (state) => {
const currentTool = state.tool;
if (currentTool !== 'move') {
state.tool = currentTool === 'brush' ? 'eraser' : 'brush';
}
},
setMaskColor: (state, action: PayloadAction<RgbaColor>) => {
state.maskColor = action.payload;
},
@ -376,9 +365,13 @@ export const canvasSlice = createSlice({
state.futureLayerStates = [];
},
addLine: (state, action: PayloadAction<number[]>) => {
const { tool, layer, brushColor, brushSize, shouldRestrictStrokesToBox } =
addLine: (
state,
action: PayloadAction<{ points: number[]; tool: CanvasTool }>
) => {
const { layer, brushColor, brushSize, shouldRestrictStrokesToBox } =
state;
const { points, tool } = action.payload;
if (tool === 'move' || tool === 'colorPicker') {
return;
@ -401,7 +394,7 @@ export const canvasSlice = createSlice({
layer,
tool,
strokeWidth: newStrokeWidth,
points: action.payload,
points,
...newColor,
};
@ -664,7 +657,6 @@ export const canvasSlice = createSlice({
...state.colorPickerColor,
a: state.brushColor.a,
};
state.tool = 'brush';
},
setMergedCanvas: (state, action: PayloadAction<CanvasImage>) => {
state.pastLayerStates.push(cloneDeep(state.layerState));
@ -771,9 +763,7 @@ export const {
setShouldSnapToGrid,
setStageCoordinates,
setStageScale,
setTool,
toggleShouldLockBoundingBox,
toggleTool,
undo,
setScaledBoundingBoxDimensions,
setShouldRestrictStrokesToBox,

View File

@ -149,7 +149,6 @@ export interface CanvasState {
stageCoordinates: Vector2d;
stageDimensions: Dimensions;
stageScale: number;
tool: CanvasTool;
generationMode?: GenerationMode;
batchIds: string[];
aspectRatio: AspectRatioState;