mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Improves bounding box behavior
This commit is contained in:
parent
bbe53841e4
commit
27ba91e74d
@ -133,7 +133,7 @@ export default function HotkeysModal({ children }: HotkeysModalProps) {
|
|||||||
{
|
{
|
||||||
title: 'Quick Toggle Brush/Eraser',
|
title: 'Quick Toggle Brush/Eraser',
|
||||||
desc: 'Quick toggle between brush and eraser',
|
desc: 'Quick toggle between brush and eraser',
|
||||||
hotkey: 'Alt',
|
hotkey: 'Z',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Decrease Brush Size',
|
title: 'Decrease Brush Size',
|
||||||
|
@ -16,10 +16,8 @@ import { useAppDispatch, useAppSelector } from '../../../app/store';
|
|||||||
import {
|
import {
|
||||||
addLine,
|
addLine,
|
||||||
addPointToCurrentLine,
|
addPointToCurrentLine,
|
||||||
setBoundingBoxCoordinate,
|
|
||||||
setCursorPosition,
|
setCursorPosition,
|
||||||
setIsDrawing,
|
setIsDrawing,
|
||||||
setIsMovingBoundingBox,
|
|
||||||
} from './inpaintingSlice';
|
} from './inpaintingSlice';
|
||||||
import { inpaintingCanvasSelector } from './inpaintingSliceSelectors';
|
import { inpaintingCanvasSelector } from './inpaintingSliceSelectors';
|
||||||
|
|
||||||
@ -30,7 +28,6 @@ import InpaintingCanvasBrushPreviewOutline from './components/InpaintingCanvasBr
|
|||||||
import Cacher from './components/Cacher';
|
import Cacher from './components/Cacher';
|
||||||
import { Vector2d } from 'konva/lib/types';
|
import { Vector2d } from 'konva/lib/types';
|
||||||
import getScaledCursorPosition from './util/getScaledCursorPosition';
|
import getScaledCursorPosition from './util/getScaledCursorPosition';
|
||||||
import _ from 'lodash';
|
|
||||||
import InpaintingBoundingBoxPreview, {
|
import InpaintingBoundingBoxPreview, {
|
||||||
InpaintingBoundingBoxPreviewOverlay,
|
InpaintingBoundingBoxPreviewOverlay,
|
||||||
} from './components/InpaintingBoundingBoxPreview';
|
} from './components/InpaintingBoundingBoxPreview';
|
||||||
@ -53,14 +50,10 @@ const InpaintingCanvas = () => {
|
|||||||
shouldShowCheckboardTransparency,
|
shouldShowCheckboardTransparency,
|
||||||
maskColor,
|
maskColor,
|
||||||
imageToInpaint,
|
imageToInpaint,
|
||||||
isMovingBoundingBox,
|
|
||||||
boundingBoxDimensions,
|
|
||||||
canvasDimensions,
|
|
||||||
boundingBoxCoordinate,
|
|
||||||
stageScale,
|
stageScale,
|
||||||
shouldShowBoundingBoxFill,
|
shouldShowBoundingBoxFill,
|
||||||
isDrawing,
|
isDrawing,
|
||||||
isTransformingBoundingBox,
|
shouldLockBoundingBox,
|
||||||
shouldShowBoundingBox,
|
shouldShowBoundingBox,
|
||||||
} = useAppSelector(inpaintingCanvasSelector);
|
} = useAppSelector(inpaintingCanvasSelector);
|
||||||
|
|
||||||
@ -91,12 +84,22 @@ const InpaintingCanvas = () => {
|
|||||||
}
|
}
|
||||||
}, [imageToInpaint, dispatch, stageScale]);
|
}, [imageToInpaint, dispatch, stageScale]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Canvas onMouseDown
|
||||||
|
*
|
||||||
|
*/
|
||||||
const handleMouseDown = useCallback(() => {
|
const handleMouseDown = useCallback(() => {
|
||||||
if (!stageRef.current) return;
|
if (!stageRef.current) return;
|
||||||
|
|
||||||
const scaledCursorPosition = getScaledCursorPosition(stageRef.current);
|
const scaledCursorPosition = getScaledCursorPosition(stageRef.current);
|
||||||
|
|
||||||
if (!scaledCursorPosition || !maskLayerRef.current) return;
|
if (
|
||||||
|
!scaledCursorPosition ||
|
||||||
|
!maskLayerRef.current ||
|
||||||
|
!shouldLockBoundingBox
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
dispatch(setIsDrawing(true));
|
dispatch(setIsDrawing(true));
|
||||||
|
|
||||||
@ -108,9 +111,15 @@ const InpaintingCanvas = () => {
|
|||||||
points: [scaledCursorPosition.x, scaledCursorPosition.y],
|
points: [scaledCursorPosition.x, scaledCursorPosition.y],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}, [dispatch, brushSize, tool]);
|
}, [dispatch, brushSize, tool, shouldLockBoundingBox]);
|
||||||
|
|
||||||
const handleMouseMove = useCallback(() => {
|
/**
|
||||||
|
*
|
||||||
|
* Canvas onMouseMove
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const handleMouseMove = useCallback(
|
||||||
|
() => {
|
||||||
if (!stageRef.current) return;
|
if (!stageRef.current) return;
|
||||||
|
|
||||||
const scaledCursorPosition = getScaledCursorPosition(stageRef.current);
|
const scaledCursorPosition = getScaledCursorPosition(stageRef.current);
|
||||||
@ -119,37 +128,12 @@ const InpaintingCanvas = () => {
|
|||||||
|
|
||||||
dispatch(setCursorPosition(scaledCursorPosition));
|
dispatch(setCursorPosition(scaledCursorPosition));
|
||||||
|
|
||||||
if (!maskLayerRef.current) {
|
if (!maskLayerRef.current || !shouldLockBoundingBox) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const deltaX = lastCursorPosition.current.x - scaledCursorPosition.x;
|
|
||||||
const deltaY = lastCursorPosition.current.y - scaledCursorPosition.y;
|
|
||||||
|
|
||||||
lastCursorPosition.current = scaledCursorPosition;
|
lastCursorPosition.current = scaledCursorPosition;
|
||||||
|
|
||||||
if (isMovingBoundingBox) {
|
|
||||||
const x = _.clamp(
|
|
||||||
Math.floor(boundingBoxCoordinate.x - deltaX),
|
|
||||||
0,
|
|
||||||
canvasDimensions.width - boundingBoxDimensions.width
|
|
||||||
);
|
|
||||||
|
|
||||||
const y = _.clamp(
|
|
||||||
Math.floor(boundingBoxCoordinate.y - deltaY),
|
|
||||||
0,
|
|
||||||
canvasDimensions.height - boundingBoxDimensions.height
|
|
||||||
);
|
|
||||||
|
|
||||||
dispatch(
|
|
||||||
setBoundingBoxCoordinate({
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isDrawing) return;
|
if (!isDrawing) return;
|
||||||
|
|
||||||
didMouseMoveRef.current = true;
|
didMouseMoveRef.current = true;
|
||||||
@ -157,20 +141,25 @@ const InpaintingCanvas = () => {
|
|||||||
dispatch(
|
dispatch(
|
||||||
addPointToCurrentLine([scaledCursorPosition.x, scaledCursorPosition.y])
|
addPointToCurrentLine([scaledCursorPosition.x, scaledCursorPosition.y])
|
||||||
);
|
);
|
||||||
}, [
|
},
|
||||||
dispatch,
|
[dispatch, isDrawing, shouldLockBoundingBox]
|
||||||
isMovingBoundingBox,
|
);
|
||||||
boundingBoxDimensions,
|
|
||||||
canvasDimensions,
|
|
||||||
boundingBoxCoordinate,
|
|
||||||
isDrawing,
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Canvas onMouseUp
|
||||||
|
*
|
||||||
|
*/
|
||||||
const handleMouseUp = useCallback(() => {
|
const handleMouseUp = useCallback(() => {
|
||||||
if (!didMouseMoveRef.current && isDrawing && stageRef.current) {
|
if (!didMouseMoveRef.current && isDrawing && stageRef.current) {
|
||||||
const scaledCursorPosition = getScaledCursorPosition(stageRef.current);
|
const scaledCursorPosition = getScaledCursorPosition(stageRef.current);
|
||||||
|
|
||||||
if (!scaledCursorPosition || !maskLayerRef.current) return;
|
if (
|
||||||
|
!scaledCursorPosition ||
|
||||||
|
!maskLayerRef.current ||
|
||||||
|
!shouldLockBoundingBox
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the current line.
|
* Extend the current line.
|
||||||
@ -185,13 +174,23 @@ const InpaintingCanvas = () => {
|
|||||||
didMouseMoveRef.current = false;
|
didMouseMoveRef.current = false;
|
||||||
}
|
}
|
||||||
dispatch(setIsDrawing(false));
|
dispatch(setIsDrawing(false));
|
||||||
}, [dispatch, isDrawing]);
|
}, [dispatch, isDrawing, shouldLockBoundingBox]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Canvas onMouseOut
|
||||||
|
*
|
||||||
|
*/
|
||||||
const handleMouseOutCanvas = useCallback(() => {
|
const handleMouseOutCanvas = useCallback(() => {
|
||||||
dispatch(setCursorPosition(null));
|
dispatch(setCursorPosition(null));
|
||||||
dispatch(setIsDrawing(false));
|
dispatch(setIsDrawing(false));
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Canvas onMouseEnter
|
||||||
|
*
|
||||||
|
*/
|
||||||
const handleMouseEnter = useCallback(
|
const handleMouseEnter = useCallback(
|
||||||
(e: KonvaEventObject<MouseEvent>) => {
|
(e: KonvaEventObject<MouseEvent>) => {
|
||||||
if (e.evt.buttons === 1) {
|
if (e.evt.buttons === 1) {
|
||||||
@ -202,8 +201,7 @@ const InpaintingCanvas = () => {
|
|||||||
if (
|
if (
|
||||||
!scaledCursorPosition ||
|
!scaledCursorPosition ||
|
||||||
!maskLayerRef.current ||
|
!maskLayerRef.current ||
|
||||||
isMovingBoundingBox ||
|
!shouldLockBoundingBox
|
||||||
isTransformingBoundingBox
|
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -219,7 +217,7 @@ const InpaintingCanvas = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[dispatch, brushSize, tool, isMovingBoundingBox, isTransformingBoundingBox]
|
[dispatch, brushSize, tool, shouldLockBoundingBox]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import Konva from 'konva';
|
import Konva from 'konva';
|
||||||
import { KonvaEventObject } from 'konva/lib/Node';
|
import { KonvaEventObject } from 'konva/lib/Node';
|
||||||
|
import { Box } from 'konva/lib/shapes/Transformer';
|
||||||
import { Vector2d } from 'konva/lib/types';
|
import { Vector2d } from 'konva/lib/types';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { useEffect, useLayoutEffect, useRef } from 'react';
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
import { Group, Rect, Transformer } from 'react-konva';
|
import { Group, Rect, Transformer } from 'react-konva';
|
||||||
import {
|
import {
|
||||||
RootState,
|
RootState,
|
||||||
@ -15,9 +16,6 @@ import {
|
|||||||
InpaintingState,
|
InpaintingState,
|
||||||
setBoundingBoxCoordinate,
|
setBoundingBoxCoordinate,
|
||||||
setBoundingBoxDimensions,
|
setBoundingBoxDimensions,
|
||||||
setIsTransformingBoundingBox,
|
|
||||||
setIsDrawing,
|
|
||||||
setShouldShowBrush,
|
|
||||||
} from '../inpaintingSlice';
|
} from '../inpaintingSlice';
|
||||||
import { rgbaColorToString } from '../util/colorToString';
|
import { rgbaColorToString } from '../util/colorToString';
|
||||||
import {
|
import {
|
||||||
@ -35,7 +33,6 @@ const boundingBoxPreviewSelector = createSelector(
|
|||||||
canvasDimensions,
|
canvasDimensions,
|
||||||
stageScale,
|
stageScale,
|
||||||
imageToInpaint,
|
imageToInpaint,
|
||||||
isMovingBoundingBox,
|
|
||||||
shouldLockBoundingBox,
|
shouldLockBoundingBox,
|
||||||
} = inpainting;
|
} = inpainting;
|
||||||
return {
|
return {
|
||||||
@ -47,7 +44,6 @@ const boundingBoxPreviewSelector = createSelector(
|
|||||||
imageToInpaint,
|
imageToInpaint,
|
||||||
dash: DASH_WIDTH / stageScale, // scale dash lengths
|
dash: DASH_WIDTH / stageScale, // scale dash lengths
|
||||||
strokeWidth: 1 / stageScale, // scale stroke thickness
|
strokeWidth: 1 / stageScale, // scale stroke thickness
|
||||||
isMovingBoundingBox,
|
|
||||||
shouldLockBoundingBox,
|
shouldLockBoundingBox,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -173,29 +169,31 @@ const InpaintingBoundingBoxPreview = () => {
|
|||||||
|
|
||||||
const scaledStep = 64 * stageScale;
|
const scaledStep = 64 * stageScale;
|
||||||
|
|
||||||
console.log(shouldLockBoundingBox);
|
const handleOnDragMove = useCallback(
|
||||||
|
(e: KonvaEventObject<DragEvent>) => {
|
||||||
|
dispatch(setBoundingBoxCoordinate({ x: e.target.x(), y: e.target.y() }));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
const dragBoundFunc = useCallback(
|
||||||
<>
|
(position: Vector2d) => {
|
||||||
<Rect
|
if (!imageToInpaint) return boundingBoxCoordinate;
|
||||||
x={boundingBoxCoordinate.x}
|
|
||||||
y={boundingBoxCoordinate.y}
|
const { x, y } = position;
|
||||||
width={boundingBoxDimensions.width}
|
|
||||||
height={boundingBoxDimensions.height}
|
const maxX = imageToInpaint.width - boundingBoxDimensions.width;
|
||||||
ref={shapeRef}
|
const maxY = imageToInpaint.height - boundingBoxDimensions.height;
|
||||||
stroke={'white'}
|
|
||||||
strokeWidth={strokeWidth}
|
const clampedX = _.clamp(x, 0, maxX);
|
||||||
listening={false}
|
const clampedY = _.clamp(y, 0, maxY);
|
||||||
onTransformStart={() => {
|
|
||||||
dispatch(setIsDrawing(false));
|
return { x: clampedX, y: clampedY };
|
||||||
dispatch(setShouldShowBrush(false));
|
},
|
||||||
dispatch(setIsTransformingBoundingBox(true));
|
[boundingBoxCoordinate, boundingBoxDimensions, imageToInpaint]
|
||||||
}}
|
);
|
||||||
onTransformEnd={() => {
|
|
||||||
dispatch(setShouldShowBrush(true));
|
const handleOnTransform = useCallback(() => {
|
||||||
dispatch(setIsTransformingBoundingBox(false));
|
|
||||||
}}
|
|
||||||
onTransform={() => {
|
|
||||||
/**
|
/**
|
||||||
* The Konva Transformer changes the object's anchor point and scale factor,
|
* The Konva Transformer changes the object's anchor point and scale factor,
|
||||||
* not its width and height. We need to un-scale the width and height before
|
* not its width and height. We need to un-scale the width and height before
|
||||||
@ -232,29 +230,10 @@ const InpaintingBoundingBoxPreview = () => {
|
|||||||
// Reset the scale now that the coords/dimensions have been un-scaled
|
// Reset the scale now that the coords/dimensions have been un-scaled
|
||||||
rect.scaleX(1);
|
rect.scaleX(1);
|
||||||
rect.scaleY(1);
|
rect.scaleY(1);
|
||||||
}}
|
}, [dispatch]);
|
||||||
/>
|
|
||||||
<Transformer
|
const anchorDragBoundFunc = useCallback(
|
||||||
enabledAnchors={shouldLockBoundingBox ? [] : undefined}
|
(
|
||||||
ref={transformerRef}
|
|
||||||
rotateEnabled={false}
|
|
||||||
anchorSize={15}
|
|
||||||
anchorFill={'rgba(212,216,234,1)'}
|
|
||||||
anchorStroke={'rgb(42,42,42)'}
|
|
||||||
borderEnabled={true}
|
|
||||||
borderStroke={'black'}
|
|
||||||
borderDash={[4, 4]}
|
|
||||||
anchorCornerRadius={3}
|
|
||||||
ignoreStroke={true}
|
|
||||||
keepRatio={false}
|
|
||||||
flipEnabled={false}
|
|
||||||
onMouseDown={(e: KonvaEventObject<MouseEvent>) => {
|
|
||||||
e.cancelBubble = true;
|
|
||||||
}}
|
|
||||||
onMouseOver={(e: KonvaEventObject<MouseEvent>) => {
|
|
||||||
e.cancelBubble = true;
|
|
||||||
}}
|
|
||||||
anchorDragBoundFunc={(
|
|
||||||
oldPos: Vector2d, // old absolute position of anchor point
|
oldPos: Vector2d, // old absolute position of anchor point
|
||||||
newPos: Vector2d, // new absolute position (potentially) of anchor point
|
newPos: Vector2d, // new absolute position (potentially) of anchor point
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
@ -307,8 +286,12 @@ const InpaintingBoundingBoxPreview = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return newCoordinate;
|
return newCoordinate;
|
||||||
}}
|
},
|
||||||
boundBoxFunc={(oldBoundBox, newBoundBox) => {
|
[scaledStep]
|
||||||
|
);
|
||||||
|
|
||||||
|
const boundBoxFunc = useCallback(
|
||||||
|
(oldBoundBox: Box, newBoundBox: Box) => {
|
||||||
/**
|
/**
|
||||||
* The transformer uses this callback to limit valid transformations.
|
* The transformer uses this callback to limit valid transformations.
|
||||||
* Unlike anchorDragBoundFunc, it does get a width and height, so
|
* Unlike anchorDragBoundFunc, it does get a width and height, so
|
||||||
@ -317,8 +300,7 @@ const InpaintingBoundingBoxPreview = () => {
|
|||||||
if (!imageToInpaint) return oldBoundBox;
|
if (!imageToInpaint) return oldBoundBox;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
newBoundBox.width + newBoundBox.x >
|
newBoundBox.width + newBoundBox.x > imageToInpaint.width * stageScale ||
|
||||||
imageToInpaint.width * stageScale ||
|
|
||||||
newBoundBox.height + newBoundBox.y >
|
newBoundBox.height + newBoundBox.y >
|
||||||
imageToInpaint.height * stageScale ||
|
imageToInpaint.height * stageScale ||
|
||||||
newBoundBox.x < 0 ||
|
newBoundBox.x < 0 ||
|
||||||
@ -328,7 +310,54 @@ const InpaintingBoundingBoxPreview = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return newBoundBox;
|
return newBoundBox;
|
||||||
|
},
|
||||||
|
[imageToInpaint, stageScale]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Rect
|
||||||
|
x={boundingBoxCoordinate.x}
|
||||||
|
y={boundingBoxCoordinate.y}
|
||||||
|
width={boundingBoxDimensions.width}
|
||||||
|
height={boundingBoxDimensions.height}
|
||||||
|
ref={shapeRef}
|
||||||
|
stroke={'white'}
|
||||||
|
strokeWidth={strokeWidth}
|
||||||
|
listening={!shouldLockBoundingBox}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
// style stage container:
|
||||||
|
const container = e?.target?.getStage()?.container();
|
||||||
|
if (!container) return;
|
||||||
|
container.style.cursor = 'move';
|
||||||
}}
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
const container = e?.target?.getStage()?.container();
|
||||||
|
if (!container) return;
|
||||||
|
container.style.cursor = 'default';
|
||||||
|
}}
|
||||||
|
draggable={!shouldLockBoundingBox}
|
||||||
|
onDragMove={handleOnDragMove}
|
||||||
|
dragBoundFunc={dragBoundFunc}
|
||||||
|
onTransform={handleOnTransform}
|
||||||
|
/>
|
||||||
|
<Transformer
|
||||||
|
ref={transformerRef}
|
||||||
|
anchorCornerRadius={3}
|
||||||
|
anchorFill={'rgba(212,216,234,1)'}
|
||||||
|
anchorSize={15}
|
||||||
|
anchorStroke={'rgb(42,42,42)'}
|
||||||
|
borderDash={[4, 4]}
|
||||||
|
borderStroke={'black'}
|
||||||
|
rotateEnabled={false}
|
||||||
|
borderEnabled={true}
|
||||||
|
flipEnabled={false}
|
||||||
|
ignoreStroke={true}
|
||||||
|
keepRatio={false}
|
||||||
|
listening={!shouldLockBoundingBox}
|
||||||
|
enabledAnchors={shouldLockBoundingBox ? [] : undefined}
|
||||||
|
boundBoxFunc={boundBoxFunc}
|
||||||
|
anchorDragBoundFunc={anchorDragBoundFunc}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -10,7 +10,9 @@ import { OptionsState } from '../../../options/optionsSlice';
|
|||||||
import { tabMap } from '../../InvokeTabs';
|
import { tabMap } from '../../InvokeTabs';
|
||||||
import {
|
import {
|
||||||
InpaintingState,
|
InpaintingState,
|
||||||
setIsMovingBoundingBox,
|
setIsDrawing,
|
||||||
|
setShouldLockBoundingBox,
|
||||||
|
setShouldShowBrush,
|
||||||
toggleTool,
|
toggleTool,
|
||||||
} from '../inpaintingSlice';
|
} from '../inpaintingSlice';
|
||||||
|
|
||||||
@ -20,14 +22,12 @@ const keyboardEventManagerSelector = createSelector(
|
|||||||
const {
|
const {
|
||||||
shouldShowMask,
|
shouldShowMask,
|
||||||
cursorPosition,
|
cursorPosition,
|
||||||
isMovingBoundingBox,
|
|
||||||
shouldLockBoundingBox,
|
shouldLockBoundingBox,
|
||||||
} = inpainting;
|
} = inpainting;
|
||||||
return {
|
return {
|
||||||
activeTabName: tabMap[options.activeTab],
|
activeTabName: tabMap[options.activeTab],
|
||||||
shouldShowMask,
|
shouldShowMask,
|
||||||
isCursorOnCanvas: Boolean(cursorPosition),
|
isCursorOnCanvas: Boolean(cursorPosition),
|
||||||
isMovingBoundingBox,
|
|
||||||
shouldLockBoundingBox,
|
shouldLockBoundingBox,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -44,7 +44,6 @@ const KeyboardEventManager = () => {
|
|||||||
shouldShowMask,
|
shouldShowMask,
|
||||||
activeTabName,
|
activeTabName,
|
||||||
isCursorOnCanvas,
|
isCursorOnCanvas,
|
||||||
isMovingBoundingBox,
|
|
||||||
shouldLockBoundingBox,
|
shouldLockBoundingBox,
|
||||||
} = useAppSelector(keyboardEventManagerSelector);
|
} = useAppSelector(keyboardEventManagerSelector);
|
||||||
|
|
||||||
@ -54,11 +53,9 @@ const KeyboardEventManager = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const listener = (e: KeyboardEvent) => {
|
const listener = (e: KeyboardEvent) => {
|
||||||
if (
|
if (
|
||||||
!['Alt', ' '].includes(e.key) ||
|
!['z', ' '].includes(e.key) ||
|
||||||
activeTabName !== 'inpainting' ||
|
activeTabName !== 'inpainting' ||
|
||||||
!shouldShowMask ||
|
!shouldShowMask
|
||||||
e.repeat ||
|
|
||||||
shouldLockBoundingBox
|
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -72,8 +69,10 @@ const KeyboardEventManager = () => {
|
|||||||
wasLastEventOverCanvas.current = false;
|
wasLastEventOverCanvas.current = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
e.stopPropagation();
|
||||||
// cursor is over canvas
|
e.preventDefault();
|
||||||
|
if (e.repeat) return;
|
||||||
|
// cursor is over canvas, we can preventDefault now
|
||||||
|
|
||||||
// if this is the first event
|
// if this is the first event
|
||||||
if (!lastEvent.current) {
|
if (!lastEvent.current) {
|
||||||
@ -87,15 +86,20 @@ const KeyboardEventManager = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case 'Alt': {
|
case 'z': {
|
||||||
dispatch(toggleTool());
|
dispatch(toggleTool());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ' ': {
|
case ' ': {
|
||||||
dispatch(setIsMovingBoundingBox(e.type === 'keydown' ? true : false));
|
if (e.type === 'keydown') {
|
||||||
|
dispatch(setIsDrawing(false));
|
||||||
|
dispatch(setShouldLockBoundingBox(false));
|
||||||
|
dispatch(setShouldShowBrush(false));
|
||||||
|
} else {
|
||||||
|
dispatch(setShouldLockBoundingBox(true));
|
||||||
|
dispatch(setShouldShowBrush(true));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,7 +120,7 @@ const KeyboardEventManager = () => {
|
|||||||
activeTabName,
|
activeTabName,
|
||||||
shouldShowMask,
|
shouldShowMask,
|
||||||
isCursorOnCanvas,
|
isCursorOnCanvas,
|
||||||
isMovingBoundingBox,
|
shouldLockBoundingBox,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -291,7 +291,19 @@ export const inpaintingSlice = createSlice({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
setBoundingBoxCoordinate: (state, action: PayloadAction<Vector2d>) => {
|
setBoundingBoxCoordinate: (state, action: PayloadAction<Vector2d>) => {
|
||||||
state.boundingBoxCoordinate = action.payload;
|
state.boundingBoxCoordinate = action.payload
|
||||||
|
// const { x, y } = action.payload;
|
||||||
|
|
||||||
|
// const maxX =
|
||||||
|
// state.canvasDimensions.width - state.boundingBoxDimensions.width;
|
||||||
|
|
||||||
|
// const maxY =
|
||||||
|
// state.canvasDimensions.height - state.boundingBoxDimensions.height;
|
||||||
|
|
||||||
|
// const clampedX = _.clamp(x, 0, maxX);
|
||||||
|
// const clampedY = _.clamp(y, 0, maxY);
|
||||||
|
|
||||||
|
// state.boundingBoxCoordinate = { x: clampedX, y: clampedY };
|
||||||
},
|
},
|
||||||
setIsMovingBoundingBox: (state, action: PayloadAction<boolean>) => {
|
setIsMovingBoundingBox: (state, action: PayloadAction<boolean>) => {
|
||||||
state.isMovingBoundingBox = action.payload;
|
state.isMovingBoundingBox = action.payload;
|
||||||
|
@ -69,35 +69,26 @@ export const inpaintingCanvasSelector = createSelector(
|
|||||||
shouldInvertMask,
|
shouldInvertMask,
|
||||||
shouldShowMask,
|
shouldShowMask,
|
||||||
shouldShowCheckboardTransparency,
|
shouldShowCheckboardTransparency,
|
||||||
shouldShowBrushPreview,
|
|
||||||
imageToInpaint,
|
imageToInpaint,
|
||||||
isMovingBoundingBox,
|
|
||||||
boundingBoxDimensions,
|
|
||||||
canvasDimensions,
|
|
||||||
boundingBoxCoordinate,
|
|
||||||
stageScale,
|
stageScale,
|
||||||
shouldShowBoundingBoxFill,
|
shouldShowBoundingBoxFill,
|
||||||
isDrawing,
|
isDrawing,
|
||||||
isTransformingBoundingBox,
|
shouldLockBoundingBox,
|
||||||
shouldShowBoundingBox,
|
shouldShowBoundingBox,
|
||||||
|
|
||||||
} = inpainting;
|
} = inpainting;
|
||||||
return {
|
return {
|
||||||
tool,
|
tool,
|
||||||
brushSize,
|
brushSize,
|
||||||
maskColor,
|
|
||||||
shouldInvertMask,
|
shouldInvertMask,
|
||||||
shouldShowMask,
|
shouldShowMask,
|
||||||
shouldShowCheckboardTransparency,
|
shouldShowCheckboardTransparency,
|
||||||
shouldShowBrushPreview,
|
maskColor,
|
||||||
imageToInpaint,
|
imageToInpaint,
|
||||||
isMovingBoundingBox,
|
|
||||||
boundingBoxDimensions,
|
|
||||||
canvasDimensions,
|
|
||||||
boundingBoxCoordinate,
|
|
||||||
stageScale,
|
stageScale,
|
||||||
shouldShowBoundingBoxFill,
|
shouldShowBoundingBoxFill,
|
||||||
isDrawing,
|
isDrawing,
|
||||||
isTransformingBoundingBox,
|
shouldLockBoundingBox,
|
||||||
shouldShowBoundingBox,
|
shouldShowBoundingBox,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user