mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
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:
parent
b501bd709f
commit
21ab650ac0
@ -14,6 +14,7 @@ import {
|
|||||||
$isMouseOverBoundingBox,
|
$isMouseOverBoundingBox,
|
||||||
$isMovingStage,
|
$isMovingStage,
|
||||||
$isTransformingBoundingBox,
|
$isTransformingBoundingBox,
|
||||||
|
$tool,
|
||||||
} from 'features/canvas/store/canvasNanostore';
|
} from 'features/canvas/store/canvasNanostore';
|
||||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
import {
|
import {
|
||||||
@ -61,7 +62,6 @@ const IAICanvas = () => {
|
|||||||
);
|
);
|
||||||
const shouldShowGrid = useAppSelector((s) => s.canvas.shouldShowGrid);
|
const shouldShowGrid = useAppSelector((s) => s.canvas.shouldShowGrid);
|
||||||
const stageScale = useAppSelector((s) => s.canvas.stageScale);
|
const stageScale = useAppSelector((s) => s.canvas.stageScale);
|
||||||
const tool = useAppSelector((s) => s.canvas.tool);
|
|
||||||
const shouldShowIntermediates = useAppSelector(
|
const shouldShowIntermediates = useAppSelector(
|
||||||
(s) => s.canvas.shouldShowIntermediates
|
(s) => s.canvas.shouldShowIntermediates
|
||||||
);
|
);
|
||||||
@ -78,6 +78,7 @@ const IAICanvas = () => {
|
|||||||
const isMovingStage = useStore($isMovingStage);
|
const isMovingStage = useStore($isMovingStage);
|
||||||
const isTransformingBoundingBox = useStore($isTransformingBoundingBox);
|
const isTransformingBoundingBox = useStore($isTransformingBoundingBox);
|
||||||
const isMouseOverBoundingBox = useStore($isMouseOverBoundingBox);
|
const isMouseOverBoundingBox = useStore($isMouseOverBoundingBox);
|
||||||
|
const tool = useStore($tool);
|
||||||
useCanvasHotkeys();
|
useCanvasHotkeys();
|
||||||
const canvasStageRefCallback = useCallback((el: Konva.Stage) => {
|
const canvasStageRefCallback = useCallback((el: Konva.Stage) => {
|
||||||
setCanvasStage(el as Konva.Stage);
|
setCanvasStage(el as Konva.Stage);
|
||||||
|
@ -8,11 +8,11 @@ import {
|
|||||||
} from 'common/util/roundDownToMultiple';
|
} from 'common/util/roundDownToMultiple';
|
||||||
import {
|
import {
|
||||||
$isDrawing,
|
$isDrawing,
|
||||||
|
$isMouseOverBoundingBox,
|
||||||
|
$isMouseOverBoundingBoxOutline,
|
||||||
$isMovingBoundingBox,
|
$isMovingBoundingBox,
|
||||||
$isTransformingBoundingBox,
|
$isTransformingBoundingBox,
|
||||||
setIsMouseOverBoundingBox,
|
$tool,
|
||||||
setIsMovingBoundingBox,
|
|
||||||
setIsTransformingBoundingBox,
|
|
||||||
} from 'features/canvas/store/canvasNanostore';
|
} from 'features/canvas/store/canvasNanostore';
|
||||||
import {
|
import {
|
||||||
aspectRatioChanged,
|
aspectRatioChanged,
|
||||||
@ -30,7 +30,7 @@ import type Konva from 'konva';
|
|||||||
import type { GroupConfig } from 'konva/lib/Group';
|
import type { GroupConfig } from 'konva/lib/Group';
|
||||||
import type { KonvaEventObject } from 'konva/lib/Node';
|
import type { KonvaEventObject } from 'konva/lib/Node';
|
||||||
import type { Vector2d } from 'konva/lib/types';
|
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 { useHotkeys } from 'react-hotkeys-hook';
|
||||||
import { Group, Rect, Transformer } from 'react-konva';
|
import { Group, Rect, Transformer } from 'react-konva';
|
||||||
|
|
||||||
@ -49,18 +49,19 @@ const IAICanvasBoundingBox = (props: IAICanvasBoundingBoxPreviewProps) => {
|
|||||||
);
|
);
|
||||||
const stageScale = useAppSelector((s) => s.canvas.stageScale);
|
const stageScale = useAppSelector((s) => s.canvas.stageScale);
|
||||||
const shouldSnapToGrid = useAppSelector((s) => s.canvas.shouldSnapToGrid);
|
const shouldSnapToGrid = useAppSelector((s) => s.canvas.shouldSnapToGrid);
|
||||||
const tool = useAppSelector((s) => s.canvas.tool);
|
|
||||||
const hitStrokeWidth = useAppSelector((s) => 20 / s.canvas.stageScale);
|
const hitStrokeWidth = useAppSelector((s) => 20 / s.canvas.stageScale);
|
||||||
const aspectRatio = useAppSelector((s) => s.canvas.aspectRatio);
|
const aspectRatio = useAppSelector((s) => s.canvas.aspectRatio);
|
||||||
const optimalDimension = useAppSelector(selectOptimalDimension);
|
const optimalDimension = useAppSelector(selectOptimalDimension);
|
||||||
const transformerRef = useRef<Konva.Transformer>(null);
|
const transformerRef = useRef<Konva.Transformer>(null);
|
||||||
const shapeRef = useRef<Konva.Rect>(null);
|
const shapeRef = useRef<Konva.Rect>(null);
|
||||||
const shift = useStore($shift);
|
const shift = useStore($shift);
|
||||||
|
const tool = useStore($tool);
|
||||||
const isDrawing = useStore($isDrawing);
|
const isDrawing = useStore($isDrawing);
|
||||||
const isMovingBoundingBox = useStore($isMovingBoundingBox);
|
const isMovingBoundingBox = useStore($isMovingBoundingBox);
|
||||||
const isTransformingBoundingBox = useStore($isTransformingBoundingBox);
|
const isTransformingBoundingBox = useStore($isTransformingBoundingBox);
|
||||||
const [isMouseOverBoundingBoxOutline, setIsMouseOverBoundingBoxOutline] =
|
const isMouseOverBoundingBoxOutline = useStore(
|
||||||
useState(false);
|
$isMouseOverBoundingBoxOutline
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!transformerRef.current || !shapeRef.current) {
|
if (!transformerRef.current || !shapeRef.current) {
|
||||||
@ -228,43 +229,43 @@ const IAICanvasBoundingBox = (props: IAICanvasBoundingBoxPreviewProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleStartedTransforming = useCallback(() => {
|
const handleStartedTransforming = useCallback(() => {
|
||||||
setIsTransformingBoundingBox(true);
|
$isTransformingBoundingBox.set(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleEndedTransforming = useCallback(() => {
|
const handleEndedTransforming = useCallback(() => {
|
||||||
setIsTransformingBoundingBox(false);
|
$isTransformingBoundingBox.set(false);
|
||||||
setIsMovingBoundingBox(false);
|
$isMovingBoundingBox.set(false);
|
||||||
setIsMouseOverBoundingBox(false);
|
$isMouseOverBoundingBox.set(false);
|
||||||
setIsMouseOverBoundingBoxOutline(false);
|
$isMouseOverBoundingBoxOutline.set(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleStartedMoving = useCallback(() => {
|
const handleStartedMoving = useCallback(() => {
|
||||||
setIsMovingBoundingBox(true);
|
$isMovingBoundingBox.set(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleEndedModifying = useCallback(() => {
|
const handleEndedModifying = useCallback(() => {
|
||||||
setIsTransformingBoundingBox(false);
|
$isTransformingBoundingBox.set(false);
|
||||||
setIsMovingBoundingBox(false);
|
$isMovingBoundingBox.set(false);
|
||||||
setIsMouseOverBoundingBox(false);
|
$isMouseOverBoundingBox.set(false);
|
||||||
setIsMouseOverBoundingBoxOutline(false);
|
$isMouseOverBoundingBoxOutline.set(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleMouseOver = useCallback(() => {
|
const handleMouseOver = useCallback(() => {
|
||||||
setIsMouseOverBoundingBoxOutline(true);
|
$isMouseOverBoundingBoxOutline.set(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleMouseOut = useCallback(() => {
|
const handleMouseOut = useCallback(() => {
|
||||||
!isTransformingBoundingBox &&
|
!isTransformingBoundingBox &&
|
||||||
!isMovingBoundingBox &&
|
!isMovingBoundingBox &&
|
||||||
setIsMouseOverBoundingBoxOutline(false);
|
$isMouseOverBoundingBoxOutline.set(false);
|
||||||
}, [isMovingBoundingBox, isTransformingBoundingBox]);
|
}, [isMovingBoundingBox, isTransformingBoundingBox]);
|
||||||
|
|
||||||
const handleMouseEnterBoundingBox = useCallback(() => {
|
const handleMouseEnterBoundingBox = useCallback(() => {
|
||||||
setIsMouseOverBoundingBox(true);
|
$isMouseOverBoundingBox.set(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleMouseLeaveBoundingBox = useCallback(() => {
|
const handleMouseLeaveBoundingBox = useCallback(() => {
|
||||||
setIsMouseOverBoundingBox(false);
|
$isMouseOverBoundingBox.set(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const stroke = useMemo(() => {
|
const stroke = useMemo(() => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Box, Flex } from '@chakra-ui/react';
|
import { Box, Flex } from '@chakra-ui/react';
|
||||||
|
import { useStore } from '@nanostores/react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIColorPicker from 'common/components/IAIColorPicker';
|
import IAIColorPicker from 'common/components/IAIColorPicker';
|
||||||
import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup';
|
import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup';
|
||||||
@ -10,14 +11,16 @@ import {
|
|||||||
InvPopoverTrigger,
|
InvPopoverTrigger,
|
||||||
} from 'common/components/InvPopover/wrapper';
|
} from 'common/components/InvPopover/wrapper';
|
||||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
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 { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
import {
|
import {
|
||||||
addEraseRect,
|
addEraseRect,
|
||||||
addFillRect,
|
addFillRect,
|
||||||
setBrushColor,
|
setBrushColor,
|
||||||
setBrushSize,
|
setBrushSize,
|
||||||
setTool,
|
|
||||||
} from 'features/canvas/store/canvasSlice';
|
} from 'features/canvas/store/canvasSlice';
|
||||||
import { InvIconButton, InvPopover } from 'index';
|
import { InvIconButton, InvPopover } from 'index';
|
||||||
import { clamp } from 'lodash-es';
|
import { clamp } from 'lodash-es';
|
||||||
@ -34,9 +37,11 @@ import {
|
|||||||
PiXBold,
|
PiXBold,
|
||||||
} from 'react-icons/pi';
|
} from 'react-icons/pi';
|
||||||
|
|
||||||
|
const marks = [1, 25, 50, 75, 100];
|
||||||
|
|
||||||
const IAICanvasToolChooserOptions = () => {
|
const IAICanvasToolChooserOptions = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const tool = useAppSelector((s) => s.canvas.tool);
|
const tool = useStore($tool);
|
||||||
const brushColor = useAppSelector((s) => s.canvas.brushColor);
|
const brushColor = useAppSelector((s) => s.canvas.brushColor);
|
||||||
const brushSize = useAppSelector((s) => s.canvas.brushSize);
|
const brushSize = useAppSelector((s) => s.canvas.brushSize);
|
||||||
const isStaging = useAppSelector(isStagingSelector);
|
const isStaging = useAppSelector(isStagingSelector);
|
||||||
@ -163,17 +168,17 @@ const IAICanvasToolChooserOptions = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleSelectBrushTool = useCallback(() => {
|
const handleSelectBrushTool = useCallback(() => {
|
||||||
dispatch(setTool('brush'));
|
$tool.set('brush');
|
||||||
resetToolInteractionState();
|
resetToolInteractionState();
|
||||||
}, [dispatch]);
|
}, []);
|
||||||
const handleSelectEraserTool = useCallback(() => {
|
const handleSelectEraserTool = useCallback(() => {
|
||||||
dispatch(setTool('eraser'));
|
$tool.set('eraser');
|
||||||
resetToolInteractionState();
|
resetToolInteractionState();
|
||||||
}, [dispatch]);
|
}, []);
|
||||||
const handleSelectColorPickerTool = useCallback(() => {
|
const handleSelectColorPickerTool = useCallback(() => {
|
||||||
dispatch(setTool('colorPicker'));
|
$tool.set('colorPicker');
|
||||||
resetToolInteractionState();
|
resetToolInteractionState();
|
||||||
}, [dispatch]);
|
}, []);
|
||||||
const handleFillRect = useCallback(() => {
|
const handleFillRect = useCallback(() => {
|
||||||
dispatch(addFillRect());
|
dispatch(addFillRect());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
@ -281,5 +286,3 @@ const IAICanvasToolChooserOptions = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default memo(IAICanvasToolChooserOptions);
|
export default memo(IAICanvasToolChooserOptions);
|
||||||
|
|
||||||
const marks = [1, 25, 50, 75, 100];
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Flex } from '@chakra-ui/react';
|
import { Flex } from '@chakra-ui/react';
|
||||||
|
import { useStore } from '@nanostores/react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup';
|
import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup';
|
||||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||||
@ -14,13 +15,13 @@ import {
|
|||||||
canvasMerged,
|
canvasMerged,
|
||||||
canvasSavedToGallery,
|
canvasSavedToGallery,
|
||||||
} from 'features/canvas/store/actions';
|
} from 'features/canvas/store/actions';
|
||||||
|
import { $tool } from 'features/canvas/store/canvasNanostore';
|
||||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
import {
|
import {
|
||||||
resetCanvas,
|
resetCanvas,
|
||||||
resetCanvasView,
|
resetCanvasView,
|
||||||
setIsMaskEnabled,
|
setIsMaskEnabled,
|
||||||
setLayer,
|
setLayer,
|
||||||
setTool,
|
|
||||||
} from 'features/canvas/store/canvasSlice';
|
} from 'features/canvas/store/canvasSlice';
|
||||||
import type { CanvasLayer } from 'features/canvas/store/canvasTypes';
|
import type { CanvasLayer } from 'features/canvas/store/canvasTypes';
|
||||||
import { LAYER_NAMES_DICT } from 'features/canvas/store/canvasTypes';
|
import { LAYER_NAMES_DICT } from 'features/canvas/store/canvasTypes';
|
||||||
@ -50,7 +51,7 @@ const IAICanvasToolbar = () => {
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const isMaskEnabled = useAppSelector((s) => s.canvas.isMaskEnabled);
|
const isMaskEnabled = useAppSelector((s) => s.canvas.isMaskEnabled);
|
||||||
const layer = useAppSelector((s) => s.canvas.layer);
|
const layer = useAppSelector((s) => s.canvas.layer);
|
||||||
const tool = useAppSelector((s) => s.canvas.tool);
|
const tool = useStore($tool);
|
||||||
const isStaging = useAppSelector(isStagingSelector);
|
const isStaging = useAppSelector(isStagingSelector);
|
||||||
const canvasBaseLayer = getCanvasBaseLayer();
|
const canvasBaseLayer = getCanvasBaseLayer();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -133,8 +134,8 @@ const IAICanvasToolbar = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleSelectMoveTool = useCallback(() => {
|
const handleSelectMoveTool = useCallback(() => {
|
||||||
dispatch(setTool('move'));
|
$tool.set('move');
|
||||||
}, [dispatch]);
|
}, []);
|
||||||
|
|
||||||
const handleClickResetCanvasView = useSingleAndDoubleClick(
|
const handleClickResetCanvasView = useSingleAndDoubleClick(
|
||||||
() => handleResetCanvasView(false),
|
() => handleResetCanvasView(false),
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useStore } from '@nanostores/react';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import {
|
import {
|
||||||
$isMovingBoundingBox,
|
$isMovingBoundingBox,
|
||||||
setIsMovingStage,
|
$isMovingStage,
|
||||||
|
$tool,
|
||||||
} from 'features/canvas/store/canvasNanostore';
|
} from 'features/canvas/store/canvasNanostore';
|
||||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
import { setStageCoordinates } from 'features/canvas/store/canvasSlice';
|
import { setStageCoordinates } from 'features/canvas/store/canvasSlice';
|
||||||
@ -12,18 +12,19 @@ import { useCallback } from 'react';
|
|||||||
const useCanvasDrag = () => {
|
const useCanvasDrag = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const isStaging = useAppSelector(isStagingSelector);
|
const isStaging = useAppSelector(isStagingSelector);
|
||||||
const tool = useAppSelector((s) => s.canvas.tool);
|
|
||||||
const isMovingBoundingBox = useStore($isMovingBoundingBox);
|
|
||||||
const handleDragStart = useCallback(() => {
|
const handleDragStart = useCallback(() => {
|
||||||
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
|
if (
|
||||||
|
!(($tool.get() === 'move' || isStaging) && !$isMovingBoundingBox.get())
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setIsMovingStage(true);
|
$isMovingStage.set(true);
|
||||||
}, [isMovingBoundingBox, isStaging, tool]);
|
}, [isStaging]);
|
||||||
|
|
||||||
const handleDragMove = useCallback(
|
const handleDragMove = useCallback(
|
||||||
(e: KonvaEventObject<MouseEvent>) => {
|
(e: KonvaEventObject<MouseEvent>) => {
|
||||||
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
|
const tool = $tool.get();
|
||||||
|
if (!((tool === 'move' || isStaging) && !$isMovingBoundingBox.get())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,15 +32,17 @@ const useCanvasDrag = () => {
|
|||||||
|
|
||||||
dispatch(setStageCoordinates(newCoordinates));
|
dispatch(setStageCoordinates(newCoordinates));
|
||||||
},
|
},
|
||||||
[dispatch, isMovingBoundingBox, isStaging, tool]
|
[dispatch, isStaging]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDragEnd = useCallback(() => {
|
const handleDragEnd = useCallback(() => {
|
||||||
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
|
if (
|
||||||
|
!(($tool.get() === 'move' || isStaging) && !$isMovingBoundingBox.get())
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setIsMovingStage(false);
|
$isMovingStage.set(false);
|
||||||
}, [isMovingBoundingBox, isStaging, tool]);
|
}, [isStaging]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleDragStart,
|
handleDragStart,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import {
|
import {
|
||||||
|
$tool,
|
||||||
|
$toolStash,
|
||||||
resetCanvasInteractionState,
|
resetCanvasInteractionState,
|
||||||
resetToolInteractionState,
|
resetToolInteractionState,
|
||||||
} from 'features/canvas/store/canvasNanostore';
|
} from 'features/canvas/store/canvasNanostore';
|
||||||
@ -9,12 +11,10 @@ import {
|
|||||||
setIsMaskEnabled,
|
setIsMaskEnabled,
|
||||||
setShouldShowBoundingBox,
|
setShouldShowBoundingBox,
|
||||||
setShouldSnapToGrid,
|
setShouldSnapToGrid,
|
||||||
setTool,
|
|
||||||
} from 'features/canvas/store/canvasSlice';
|
} from 'features/canvas/store/canvasSlice';
|
||||||
import type { CanvasTool } from 'features/canvas/store/canvasTypes';
|
|
||||||
import { getCanvasStage } from 'features/canvas/util/konvaInstanceProvider';
|
import { getCanvasStage } from 'features/canvas/util/konvaInstanceProvider';
|
||||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||||
import { useCallback, useRef } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
|
|
||||||
const useInpaintingCanvasHotkeys = () => {
|
const useInpaintingCanvasHotkeys = () => {
|
||||||
@ -23,11 +23,9 @@ const useInpaintingCanvasHotkeys = () => {
|
|||||||
const shouldShowBoundingBox = useAppSelector(
|
const shouldShowBoundingBox = useAppSelector(
|
||||||
(s) => s.canvas.shouldShowBoundingBox
|
(s) => s.canvas.shouldShowBoundingBox
|
||||||
);
|
);
|
||||||
const tool = useAppSelector((s) => s.canvas.tool);
|
|
||||||
const isStaging = useAppSelector(isStagingSelector);
|
const isStaging = useAppSelector(isStagingSelector);
|
||||||
const isMaskEnabled = useAppSelector((s) => s.canvas.isMaskEnabled);
|
const isMaskEnabled = useAppSelector((s) => s.canvas.isMaskEnabled);
|
||||||
const shouldSnapToGrid = useAppSelector((s) => s.canvas.shouldSnapToGrid);
|
const shouldSnapToGrid = useAppSelector((s) => s.canvas.shouldSnapToGrid);
|
||||||
const previousToolRef = useRef<CanvasTool | null>(null);
|
|
||||||
const canvasStage = getCanvasStage();
|
const canvasStage = getCanvasStage();
|
||||||
|
|
||||||
// Beta Keys
|
// Beta Keys
|
||||||
@ -96,37 +94,53 @@ const useInpaintingCanvasHotkeys = () => {
|
|||||||
[activeTabName, shouldShowBoundingBox]
|
[activeTabName, shouldShowBoundingBox]
|
||||||
);
|
);
|
||||||
|
|
||||||
useHotkeys(
|
useEffect(() => {
|
||||||
['space'],
|
window.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === ' ' && !e.repeat) {
|
||||||
|
console.log('spaceeee');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onKeyDown = useCallback(
|
||||||
(e: KeyboardEvent) => {
|
(e: KeyboardEvent) => {
|
||||||
if (e.repeat) {
|
if (e.repeat || e.key !== ' ') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($toolStash.get() || $tool.get() === 'move') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasStage?.container().focus();
|
canvasStage?.container().focus();
|
||||||
|
$toolStash.set($tool.get());
|
||||||
if (tool !== 'move') {
|
$tool.set('move');
|
||||||
previousToolRef.current = tool;
|
resetToolInteractionState();
|
||||||
dispatch(setTool('move'));
|
|
||||||
resetToolInteractionState();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
tool === 'move' &&
|
|
||||||
previousToolRef.current &&
|
|
||||||
previousToolRef.current !== 'move'
|
|
||||||
) {
|
|
||||||
dispatch(setTool(previousToolRef.current));
|
|
||||||
previousToolRef.current = 'move';
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
[canvasStage]
|
||||||
keyup: true,
|
|
||||||
keydown: true,
|
|
||||||
preventDefault: true,
|
|
||||||
},
|
|
||||||
[tool, previousToolRef]
|
|
||||||
);
|
);
|
||||||
|
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;
|
export default useInpaintingCanvasHotkeys;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import {
|
import {
|
||||||
setIsDrawing,
|
$isDrawing,
|
||||||
setIsMovingStage,
|
$isMovingStage,
|
||||||
|
$tool,
|
||||||
} from 'features/canvas/store/canvasNanostore';
|
} from 'features/canvas/store/canvasNanostore';
|
||||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
import { addLine } from 'features/canvas/store/canvasSlice';
|
import { addLine } from 'features/canvas/store/canvasSlice';
|
||||||
@ -15,7 +16,6 @@ import useColorPicker from './useColorUnderCursor';
|
|||||||
|
|
||||||
const useCanvasMouseDown = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
const useCanvasMouseDown = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const tool = useAppSelector((s) => s.canvas.tool);
|
|
||||||
const isStaging = useAppSelector(isStagingSelector);
|
const isStaging = useAppSelector(isStagingSelector);
|
||||||
const { commitColorUnderCursor } = useColorPicker();
|
const { commitColorUnderCursor } = useColorPicker();
|
||||||
|
|
||||||
@ -26,9 +26,10 @@ const useCanvasMouseDown = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stageRef.current.container().focus();
|
stageRef.current.container().focus();
|
||||||
|
const tool = $tool.get();
|
||||||
|
|
||||||
if (tool === 'move' || isStaging) {
|
if (tool === 'move' || isStaging) {
|
||||||
setIsMovingStage(true);
|
$isMovingStage.set(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,12 +46,17 @@ const useCanvasMouseDown = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
|||||||
|
|
||||||
e.evt.preventDefault();
|
e.evt.preventDefault();
|
||||||
|
|
||||||
setIsDrawing(true);
|
$isDrawing.set(true);
|
||||||
|
|
||||||
// Add a new line starting from the current cursor position.
|
// 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]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useStore } from '@nanostores/react';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import {
|
import {
|
||||||
|
$cursorPosition,
|
||||||
$isDrawing,
|
$isDrawing,
|
||||||
setCursorPosition,
|
$tool,
|
||||||
} from 'features/canvas/store/canvasNanostore';
|
} from 'features/canvas/store/canvasNanostore';
|
||||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
import { addPointToCurrentLine } from 'features/canvas/store/canvasSlice';
|
import { addPointToCurrentLine } from 'features/canvas/store/canvasSlice';
|
||||||
@ -20,8 +20,6 @@ const useCanvasMouseMove = (
|
|||||||
lastCursorPositionRef: MutableRefObject<Vector2d>
|
lastCursorPositionRef: MutableRefObject<Vector2d>
|
||||||
) => {
|
) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const isDrawing = useStore($isDrawing);
|
|
||||||
const tool = useAppSelector((s) => s.canvas.tool);
|
|
||||||
const isStaging = useAppSelector(isStagingSelector);
|
const isStaging = useAppSelector(isStagingSelector);
|
||||||
const { updateColorUnderCursor } = useColorPicker();
|
const { updateColorUnderCursor } = useColorPicker();
|
||||||
|
|
||||||
@ -36,16 +34,17 @@ const useCanvasMouseMove = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCursorPosition(scaledCursorPosition);
|
$cursorPosition.set(scaledCursorPosition);
|
||||||
|
|
||||||
lastCursorPositionRef.current = scaledCursorPosition;
|
lastCursorPositionRef.current = scaledCursorPosition;
|
||||||
|
const tool = $tool.get();
|
||||||
|
|
||||||
if (tool === 'colorPicker') {
|
if (tool === 'colorPicker') {
|
||||||
updateColorUnderCursor();
|
updateColorUnderCursor();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDrawing || tool === 'move' || isStaging) {
|
if (!$isDrawing.get() || tool === 'move' || isStaging) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,11 +55,9 @@ const useCanvasMouseMove = (
|
|||||||
}, [
|
}, [
|
||||||
didMouseMoveRef,
|
didMouseMoveRef,
|
||||||
dispatch,
|
dispatch,
|
||||||
isDrawing,
|
|
||||||
isStaging,
|
isStaging,
|
||||||
lastCursorPositionRef,
|
lastCursorPositionRef,
|
||||||
stageRef,
|
stageRef,
|
||||||
tool,
|
|
||||||
updateColorUnderCursor,
|
updateColorUnderCursor,
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
@ -2,8 +2,8 @@ import { useStore } from '@nanostores/react';
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import {
|
import {
|
||||||
$isDrawing,
|
$isDrawing,
|
||||||
setIsDrawing,
|
$isMovingStage,
|
||||||
setIsMovingStage,
|
$tool,
|
||||||
} from 'features/canvas/store/canvasNanostore';
|
} from 'features/canvas/store/canvasNanostore';
|
||||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
import { addPointToCurrentLine } from 'features/canvas/store/canvasSlice';
|
import { addPointToCurrentLine } from 'features/canvas/store/canvasSlice';
|
||||||
@ -18,12 +18,11 @@ const useCanvasMouseUp = (
|
|||||||
) => {
|
) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const isDrawing = useStore($isDrawing);
|
const isDrawing = useStore($isDrawing);
|
||||||
const tool = useAppSelector((s) => s.canvas.tool);
|
|
||||||
const isStaging = useAppSelector(isStagingSelector);
|
const isStaging = useAppSelector(isStagingSelector);
|
||||||
|
|
||||||
return useCallback(() => {
|
return useCallback(() => {
|
||||||
if (tool === 'move' || isStaging) {
|
if ($tool.get() === 'move' || isStaging) {
|
||||||
setIsMovingStage(false);
|
$isMovingStage.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,8 +45,8 @@ const useCanvasMouseUp = (
|
|||||||
} else {
|
} else {
|
||||||
didMouseMoveRef.current = false;
|
didMouseMoveRef.current = false;
|
||||||
}
|
}
|
||||||
setIsDrawing(false);
|
$isDrawing.set(false);
|
||||||
}, [didMouseMoveRef, dispatch, isDrawing, isStaging, stageRef, tool]);
|
}, [didMouseMoveRef, dispatch, isDrawing, isStaging, stageRef]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useCanvasMouseUp;
|
export default useCanvasMouseUp;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
|
import { $tool } from 'features/canvas/store/canvasNanostore';
|
||||||
import {
|
import {
|
||||||
commitColorPickerColor,
|
commitColorPickerColor,
|
||||||
setColorPickerColor,
|
setColorPickerColor,
|
||||||
@ -51,6 +52,7 @@ const useColorPicker = () => {
|
|||||||
|
|
||||||
const commitColorUnderCursor = useCallback(() => {
|
const commitColorUnderCursor = useCallback(() => {
|
||||||
dispatch(commitColorPickerColor());
|
dispatch(commitColorPickerColor());
|
||||||
|
$tool.set('brush')
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
return { updateColorUnderCursor, commitColorUnderCursor };
|
return { updateColorUnderCursor, commitColorUnderCursor };
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
|
import type { CanvasTool } from 'features/canvas/store/canvasTypes';
|
||||||
import type { Vector2d } from 'konva/lib/types';
|
import type { Vector2d } from 'konva/lib/types';
|
||||||
import { atom, computed } from 'nanostores';
|
import { atom, computed } from 'nanostores';
|
||||||
|
|
||||||
export const $cursorPosition = atom<Vector2d | null>(null);
|
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 $isDrawing = atom<boolean>(false);
|
||||||
export const $isMouseOverBoundingBox = atom<boolean>(false);
|
export const $isMouseOverBoundingBox = atom<boolean>(false);
|
||||||
export const $isMoveBoundingBoxKeyHeld = 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 $isMovingBoundingBox = atom<boolean>(false);
|
||||||
export const $isMovingStage = atom<boolean>(false);
|
export const $isMovingStage = atom<boolean>(false);
|
||||||
export const $isTransformingBoundingBox = atom<boolean>(false);
|
export const $isTransformingBoundingBox = atom<boolean>(false);
|
||||||
|
export const $isMouseOverBoundingBoxOutline = atom<boolean>(false);
|
||||||
export const $isModifyingBoundingBox = computed(
|
export const $isModifyingBoundingBox = computed(
|
||||||
[$isTransformingBoundingBox, $isMovingBoundingBox],
|
[$isTransformingBoundingBox, $isMovingBoundingBox],
|
||||||
(isTransformingBoundingBox, isMovingBoundingBox) =>
|
(isTransformingBoundingBox, isMovingBoundingBox) =>
|
||||||
@ -25,49 +29,13 @@ export const resetCanvasInteractionState = () => {
|
|||||||
$isMovingStage.set(false);
|
$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 = () => {
|
export const resetToolInteractionState = () => {
|
||||||
setIsTransformingBoundingBox(false);
|
$isTransformingBoundingBox.set(false);
|
||||||
setIsMouseOverBoundingBox(false);
|
$isMouseOverBoundingBox.set(false);
|
||||||
setIsMovingBoundingBox(false);
|
$isMovingBoundingBox.set(false);
|
||||||
setIsMovingStage(false);
|
$isMovingStage.set(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setCanvasInteractionStateMouseOut = () => {
|
export const setCanvasInteractionStateMouseOut = () => {
|
||||||
setCursorPosition(null);
|
$cursorPosition.set(null);
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,6 @@ import calculateScale from 'features/canvas/util/calculateScale';
|
|||||||
import { STAGE_PADDING_PERCENTAGE } from 'features/canvas/util/constants';
|
import { STAGE_PADDING_PERCENTAGE } from 'features/canvas/util/constants';
|
||||||
import floorCoordinates from 'features/canvas/util/floorCoordinates';
|
import floorCoordinates from 'features/canvas/util/floorCoordinates';
|
||||||
import getScaledBoundingBoxDimensions from 'features/canvas/util/getScaledBoundingBoxDimensions';
|
import getScaledBoundingBoxDimensions from 'features/canvas/util/getScaledBoundingBoxDimensions';
|
||||||
import roundDimensionsToMultiple from 'features/canvas/util/roundDimensionsToMultiple';
|
|
||||||
import { initialAspectRatioState } from 'features/parameters/components/ImageSize/constants';
|
import { initialAspectRatioState } from 'features/parameters/components/ImageSize/constants';
|
||||||
import type { AspectRatioState } from 'features/parameters/components/ImageSize/types';
|
import type { AspectRatioState } from 'features/parameters/components/ImageSize/types';
|
||||||
import { modelChanged } from 'features/parameters/store/generationSlice';
|
import { modelChanged } from 'features/parameters/store/generationSlice';
|
||||||
@ -86,7 +85,6 @@ export const initialCanvasState: CanvasState = {
|
|||||||
stageCoordinates: { x: 0, y: 0 },
|
stageCoordinates: { x: 0, y: 0 },
|
||||||
stageDimensions: { width: 0, height: 0 },
|
stageDimensions: { width: 0, height: 0 },
|
||||||
stageScale: 1,
|
stageScale: 1,
|
||||||
tool: 'brush',
|
|
||||||
batchIds: [],
|
batchIds: [],
|
||||||
aspectRatio: {
|
aspectRatio: {
|
||||||
id: '1:1',
|
id: '1:1',
|
||||||
@ -119,18 +117,9 @@ export const canvasSlice = createSlice({
|
|||||||
name: 'canvas',
|
name: 'canvas',
|
||||||
initialState: initialCanvasState,
|
initialState: initialCanvasState,
|
||||||
reducers: {
|
reducers: {
|
||||||
setTool: (state, action: PayloadAction<CanvasTool>) => {
|
|
||||||
state.tool = action.payload;
|
|
||||||
},
|
|
||||||
setLayer: (state, action: PayloadAction<CanvasLayer>) => {
|
setLayer: (state, action: PayloadAction<CanvasLayer>) => {
|
||||||
state.layer = action.payload;
|
state.layer = action.payload;
|
||||||
},
|
},
|
||||||
toggleTool: (state) => {
|
|
||||||
const currentTool = state.tool;
|
|
||||||
if (currentTool !== 'move') {
|
|
||||||
state.tool = currentTool === 'brush' ? 'eraser' : 'brush';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setMaskColor: (state, action: PayloadAction<RgbaColor>) => {
|
setMaskColor: (state, action: PayloadAction<RgbaColor>) => {
|
||||||
state.maskColor = action.payload;
|
state.maskColor = action.payload;
|
||||||
},
|
},
|
||||||
@ -376,9 +365,13 @@ export const canvasSlice = createSlice({
|
|||||||
|
|
||||||
state.futureLayerStates = [];
|
state.futureLayerStates = [];
|
||||||
},
|
},
|
||||||
addLine: (state, action: PayloadAction<number[]>) => {
|
addLine: (
|
||||||
const { tool, layer, brushColor, brushSize, shouldRestrictStrokesToBox } =
|
state,
|
||||||
|
action: PayloadAction<{ points: number[]; tool: CanvasTool }>
|
||||||
|
) => {
|
||||||
|
const { layer, brushColor, brushSize, shouldRestrictStrokesToBox } =
|
||||||
state;
|
state;
|
||||||
|
const { points, tool } = action.payload;
|
||||||
|
|
||||||
if (tool === 'move' || tool === 'colorPicker') {
|
if (tool === 'move' || tool === 'colorPicker') {
|
||||||
return;
|
return;
|
||||||
@ -401,7 +394,7 @@ export const canvasSlice = createSlice({
|
|||||||
layer,
|
layer,
|
||||||
tool,
|
tool,
|
||||||
strokeWidth: newStrokeWidth,
|
strokeWidth: newStrokeWidth,
|
||||||
points: action.payload,
|
points,
|
||||||
...newColor,
|
...newColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -664,7 +657,6 @@ export const canvasSlice = createSlice({
|
|||||||
...state.colorPickerColor,
|
...state.colorPickerColor,
|
||||||
a: state.brushColor.a,
|
a: state.brushColor.a,
|
||||||
};
|
};
|
||||||
state.tool = 'brush';
|
|
||||||
},
|
},
|
||||||
setMergedCanvas: (state, action: PayloadAction<CanvasImage>) => {
|
setMergedCanvas: (state, action: PayloadAction<CanvasImage>) => {
|
||||||
state.pastLayerStates.push(cloneDeep(state.layerState));
|
state.pastLayerStates.push(cloneDeep(state.layerState));
|
||||||
@ -771,9 +763,7 @@ export const {
|
|||||||
setShouldSnapToGrid,
|
setShouldSnapToGrid,
|
||||||
setStageCoordinates,
|
setStageCoordinates,
|
||||||
setStageScale,
|
setStageScale,
|
||||||
setTool,
|
|
||||||
toggleShouldLockBoundingBox,
|
toggleShouldLockBoundingBox,
|
||||||
toggleTool,
|
|
||||||
undo,
|
undo,
|
||||||
setScaledBoundingBoxDimensions,
|
setScaledBoundingBoxDimensions,
|
||||||
setShouldRestrictStrokesToBox,
|
setShouldRestrictStrokesToBox,
|
||||||
|
@ -149,7 +149,6 @@ export interface CanvasState {
|
|||||||
stageCoordinates: Vector2d;
|
stageCoordinates: Vector2d;
|
||||||
stageDimensions: Dimensions;
|
stageDimensions: Dimensions;
|
||||||
stageScale: number;
|
stageScale: number;
|
||||||
tool: CanvasTool;
|
|
||||||
generationMode?: GenerationMode;
|
generationMode?: GenerationMode;
|
||||||
batchIds: string[];
|
batchIds: string[];
|
||||||
aspectRatio: AspectRatioState;
|
aspectRatio: AspectRatioState;
|
||||||
|
Loading…
Reference in New Issue
Block a user