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,
|
||||
$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);
|
||||
|
@ -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(() => {
|
||||
|
@ -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];
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
]);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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 };
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -149,7 +149,6 @@ export interface CanvasState {
|
||||
stageCoordinates: Vector2d;
|
||||
stageDimensions: Dimensions;
|
||||
stageScale: number;
|
||||
tool: CanvasTool;
|
||||
generationMode?: GenerationMode;
|
||||
batchIds: string[];
|
||||
aspectRatio: AspectRatioState;
|
||||
|
Loading…
Reference in New Issue
Block a user