diff --git a/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.tsx b/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.tsx index 40360275eb..0af706896c 100644 --- a/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.tsx +++ b/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.tsx @@ -1,3 +1,4 @@ +import { Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import _ from 'lodash'; import { ChangeEvent } from 'react'; @@ -18,6 +19,7 @@ import { roundDownToMultiple } from '../../../../common/util/roundDownToMultiple import { InpaintingState, setBoundingBoxDimensions, + setShouldLockBoundingBox, setShouldShowBoundingBox, setShouldShowBoundingBoxFill, } from '../../../tabs/Inpainting/inpaintingSlice'; @@ -32,6 +34,7 @@ const boundingBoxDimensionsSelector = createSelector( shouldShowBoundingBoxFill, pastLines, futureLines, + shouldLockBoundingBox, } = inpainting; return { canvasDimensions, @@ -40,6 +43,7 @@ const boundingBoxDimensionsSelector = createSelector( shouldShowBoundingBoxFill, pastLines, futureLines, + shouldLockBoundingBox, }; }, { @@ -56,6 +60,7 @@ const BoundingBoxSettings = () => { boundingBoxDimensions, shouldShowBoundingBox, shouldShowBoundingBoxFill, + shouldLockBoundingBox, } = useAppSelector(boundingBoxDimensionsSelector); const handleChangeBoundingBoxWidth = (v: number) => { @@ -73,6 +78,10 @@ const BoundingBoxSettings = () => { dispatch(setShouldShowBoundingBoxFill(!shouldShowBoundingBoxFill)); }; + const handleChangeShouldLockBoundingBox = () => { + dispatch(setShouldLockBoundingBox(!shouldLockBoundingBox)); + }; + const handleResetWidth = () => { dispatch( setBoundingBoxDimensions({ @@ -169,13 +178,22 @@ const BoundingBoxSettings = () => { } /> - + + + + ); diff --git a/frontend/src/features/tabs/Inpainting/InpaintingCanvas.tsx b/frontend/src/features/tabs/Inpainting/InpaintingCanvas.tsx index ff60baa216..14624ae9bb 100644 --- a/frontend/src/features/tabs/Inpainting/InpaintingCanvas.tsx +++ b/frontend/src/features/tabs/Inpainting/InpaintingCanvas.tsx @@ -60,7 +60,7 @@ const InpaintingCanvas = () => { stageScale, shouldShowBoundingBoxFill, isDrawing, - isBoundingBoxTransforming, + isTransformingBoundingBox, shouldShowBoundingBox, } = useAppSelector(inpaintingCanvasSelector); @@ -204,7 +204,7 @@ const InpaintingCanvas = () => { !scaledCursorPosition || !maskLayerRef.current || isMovingBoundingBox || - isBoundingBoxTransforming + isTransformingBoundingBox ) return; @@ -220,7 +220,7 @@ const InpaintingCanvas = () => { ); } }, - [dispatch, brushSize, tool, isMovingBoundingBox, isBoundingBoxTransforming] + [dispatch, brushSize, tool, isMovingBoundingBox, isTransformingBoundingBox] ); return ( diff --git a/frontend/src/features/tabs/Inpainting/components/Cacher.tsx b/frontend/src/features/tabs/Inpainting/components/Cacher.tsx index 086f197623..30ad59b9fe 100644 --- a/frontend/src/features/tabs/Inpainting/components/Cacher.tsx +++ b/frontend/src/features/tabs/Inpainting/components/Cacher.tsx @@ -27,6 +27,12 @@ const Cacher = () => { imageToInpaint, shouldShowBrush, shouldShowBoundingBoxFill, + shouldLockBoundingBox, + stageScale, + pastLines, + futureLines, + needsRepaint, + isDrawing, } = useAppSelector((state: RootState) => state.inpainting); useLayoutEffect(() => { @@ -52,6 +58,12 @@ const Cacher = () => { imageToInpaint, shouldShowBrush, shouldShowBoundingBoxFill, + shouldLockBoundingBox, + stageScale, + pastLines, + futureLines, + needsRepaint, + isDrawing, ]); return null; diff --git a/frontend/src/features/tabs/Inpainting/components/InpaintingBoundingBoxPreview.tsx b/frontend/src/features/tabs/Inpainting/components/InpaintingBoundingBoxPreview.tsx index 5b81e73bf7..ebba337065 100644 --- a/frontend/src/features/tabs/Inpainting/components/InpaintingBoundingBoxPreview.tsx +++ b/frontend/src/features/tabs/Inpainting/components/InpaintingBoundingBoxPreview.tsx @@ -3,7 +3,7 @@ import Konva from 'konva'; import { KonvaEventObject } from 'konva/lib/Node'; import { Vector2d } from 'konva/lib/types'; import _ from 'lodash'; -import { useEffect, useRef } from 'react'; +import { useEffect, useLayoutEffect, useRef } from 'react'; import { Group, Rect, Transformer } from 'react-konva'; import { RootState, @@ -15,7 +15,7 @@ import { InpaintingState, setBoundingBoxCoordinate, setBoundingBoxDimensions, - setIsBoundingBoxTransforming, + setIsTransformingBoundingBox, setIsDrawing, setShouldShowBrush, } from '../inpaintingSlice'; @@ -36,6 +36,7 @@ const boundingBoxPreviewSelector = createSelector( stageScale, imageToInpaint, isMovingBoundingBox, + shouldLockBoundingBox, } = inpainting; return { boundingBoxCoordinate, @@ -47,6 +48,7 @@ const boundingBoxPreviewSelector = createSelector( dash: DASH_WIDTH / stageScale, // scale dash lengths strokeWidth: 1 / stageScale, // scale stroke thickness isMovingBoundingBox, + shouldLockBoundingBox, }; }, { @@ -157,6 +159,7 @@ const InpaintingBoundingBoxPreview = () => { strokeWidth, stageScale, imageToInpaint, + shouldLockBoundingBox, } = useAppSelector(boundingBoxPreviewSelector); const transformerRef = useRef(null); @@ -166,10 +169,12 @@ const InpaintingBoundingBoxPreview = () => { if (!transformerRef.current || !shapeRef.current) return; transformerRef.current.nodes([shapeRef.current]); transformerRef.current.getLayer()?.batchDraw(); - }, []); + }, [shouldLockBoundingBox]); const scaledStep = 64 * stageScale; + console.log(shouldLockBoundingBox); + return ( <> { onTransformStart={() => { dispatch(setIsDrawing(false)); dispatch(setShouldShowBrush(false)); - dispatch(setIsBoundingBoxTransforming(true)); + dispatch(setIsTransformingBoundingBox(true)); }} onTransformEnd={() => { dispatch(setShouldShowBrush(true)); - dispatch(setIsBoundingBoxTransforming(false)); + dispatch(setIsTransformingBoundingBox(false)); }} onTransform={() => { /** @@ -230,6 +235,7 @@ const InpaintingBoundingBoxPreview = () => { }} /> { onMouseDown={(e: KonvaEventObject) => { e.cancelBubble = true; }} + onMouseOver={(e: KonvaEventObject) => { + e.cancelBubble = true; + }} anchorDragBoundFunc={( oldPos: Vector2d, // old absolute position of anchor point newPos: Vector2d, // new absolute position (potentially) of anchor point diff --git a/frontend/src/features/tabs/Inpainting/components/KeyboardEventManager.tsx b/frontend/src/features/tabs/Inpainting/components/KeyboardEventManager.tsx index bf26065837..c087cb08e7 100644 --- a/frontend/src/features/tabs/Inpainting/components/KeyboardEventManager.tsx +++ b/frontend/src/features/tabs/Inpainting/components/KeyboardEventManager.tsx @@ -11,19 +11,24 @@ import { tabMap } from '../../InvokeTabs'; import { InpaintingState, setIsMovingBoundingBox, - toggleIsMovingBoundingBox, toggleTool, } from '../inpaintingSlice'; const keyboardEventManagerSelector = createSelector( [(state: RootState) => state.options, (state: RootState) => state.inpainting], (options: OptionsState, inpainting: InpaintingState) => { - const { shouldShowMask, cursorPosition, isMovingBoundingBox } = inpainting; + const { + shouldShowMask, + cursorPosition, + isMovingBoundingBox, + shouldLockBoundingBox, + } = inpainting; return { activeTabName: tabMap[options.activeTab], shouldShowMask, isCursorOnCanvas: Boolean(cursorPosition), isMovingBoundingBox, + shouldLockBoundingBox, }; }, { @@ -40,9 +45,9 @@ const KeyboardEventManager = () => { activeTabName, isCursorOnCanvas, isMovingBoundingBox, + shouldLockBoundingBox, } = useAppSelector(keyboardEventManagerSelector); - const isFirstEvent = useRef(true); const wasLastEventOverCanvas = useRef(false); const lastEvent = useRef(null); @@ -52,7 +57,8 @@ const KeyboardEventManager = () => { !['Alt', ' '].includes(e.key) || activeTabName !== 'inpainting' || !shouldShowMask || - e.repeat + e.repeat || + shouldLockBoundingBox ) { return; } diff --git a/frontend/src/features/tabs/Inpainting/inpaintingSlice.ts b/frontend/src/features/tabs/Inpainting/inpaintingSlice.ts index 2417ce808f..94d2c5ce25 100644 --- a/frontend/src/features/tabs/Inpainting/inpaintingSlice.ts +++ b/frontend/src/features/tabs/Inpainting/inpaintingSlice.ts @@ -40,7 +40,7 @@ export interface InpaintingState { boundingBoxPreviewFill: RgbaColor; shouldShowBoundingBox: boolean; shouldShowBoundingBoxFill: boolean; - isBoundingBoxTransforming: boolean; + isTransformingBoundingBox: boolean; lines: MaskLine[]; pastLines: MaskLine[][]; futureLines: MaskLine[][]; @@ -55,6 +55,7 @@ export interface InpaintingState { isDrawing: boolean; shouldUseInpaintReplace: boolean; inpaintReplace: number; + shouldLockBoundingBox: boolean; } const initialInpaintingState: InpaintingState = { @@ -67,7 +68,7 @@ const initialInpaintingState: InpaintingState = { boundingBoxPreviewFill: { r: 0, g: 0, b: 0, a: 0.7 }, shouldShowBoundingBox: false, shouldShowBoundingBoxFill: false, - isBoundingBoxTransforming: false, + isTransformingBoundingBox: false, cursorPosition: null, lines: [], pastLines: [], @@ -83,6 +84,7 @@ const initialInpaintingState: InpaintingState = { stageScale: 1, shouldUseInpaintReplace: false, inpaintReplace: 1, + shouldLockBoundingBox: true, }; const initialState: InpaintingState = initialInpaintingState; @@ -310,8 +312,8 @@ export const inpaintingSlice = createSlice({ setShouldShowBoundingBoxFill: (state, action: PayloadAction) => { state.shouldShowBoundingBoxFill = action.payload; }, - setIsBoundingBoxTransforming: (state, action: PayloadAction) => { - state.isBoundingBoxTransforming = action.payload; + setIsTransformingBoundingBox: (state, action: PayloadAction) => { + state.isTransformingBoundingBox = action.payload; }, setIsDrawing: (state, action: PayloadAction) => { state.isDrawing = action.payload; @@ -329,6 +331,9 @@ export const inpaintingSlice = createSlice({ setInpaintReplace: (state, action: PayloadAction) => { state.inpaintReplace = action.payload; }, + setShouldLockBoundingBox: (state, action: PayloadAction) => { + state.shouldLockBoundingBox = action.payload; + }, }, }); @@ -357,13 +362,14 @@ export const { toggleTool, toggleIsMovingBoundingBox, setShouldShowBoundingBoxFill, - setIsBoundingBoxTransforming, + setIsTransformingBoundingBox, setIsDrawing, setShouldShowBrush, setShouldShowBoundingBox, setClearBrushHistory, setShouldUseInpaintReplace, setInpaintReplace, + setShouldLockBoundingBox, } = inpaintingSlice.actions; export default inpaintingSlice.reducer; diff --git a/frontend/src/features/tabs/Inpainting/inpaintingSliceSelectors.ts b/frontend/src/features/tabs/Inpainting/inpaintingSliceSelectors.ts index 65dcd29311..634bb4077d 100644 --- a/frontend/src/features/tabs/Inpainting/inpaintingSliceSelectors.ts +++ b/frontend/src/features/tabs/Inpainting/inpaintingSliceSelectors.ts @@ -78,7 +78,7 @@ export const inpaintingCanvasSelector = createSelector( stageScale, shouldShowBoundingBoxFill, isDrawing, - isBoundingBoxTransforming, + isTransformingBoundingBox, shouldShowBoundingBox, } = inpainting; return { @@ -97,7 +97,7 @@ export const inpaintingCanvasSelector = createSelector( stageScale, shouldShowBoundingBoxFill, isDrawing, - isBoundingBoxTransforming, + isTransformingBoundingBox, shouldShowBoundingBox, }; },