Adds lock bounding box

This commit is contained in:
psychedelicious 2022-10-28 11:37:46 +11:00
parent 43de16cae4
commit 55a8da0f02
7 changed files with 77 additions and 26 deletions

View File

@ -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 = () => {
}
/>
</div>
<IAICheckbox
label="Darken Outside Box"
isChecked={shouldShowBoundingBoxFill}
onChange={handleChangeShouldShowBoundingBoxFill}
styleClass="inpainting-bounding-box-darken"
isDisabled={!shouldShowBoundingBox}
/>
<Flex alignItems={'center'} justifyContent={'space-between'}>
<IAICheckbox
label="Darken Outside Box"
isChecked={shouldShowBoundingBoxFill}
onChange={handleChangeShouldShowBoundingBoxFill}
styleClass="inpainting-bounding-box-darken"
isDisabled={!shouldShowBoundingBox}
/>
<IAICheckbox
label="Lock Bounding Box"
isChecked={shouldLockBoundingBox}
onChange={handleChangeShouldLockBoundingBox}
styleClass="inpainting-bounding-box-darken"
isDisabled={!shouldShowBoundingBox}
/>
</Flex>
</div>
</div>
);

View File

@ -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 (

View File

@ -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;

View File

@ -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<Konva.Transformer>(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 (
<>
<Rect
@ -184,11 +189,11 @@ const InpaintingBoundingBoxPreview = () => {
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 = () => {
}}
/>
<Transformer
enabledAnchors={shouldLockBoundingBox ? [] : undefined}
ref={transformerRef}
rotateEnabled={false}
anchorSize={15}
@ -245,6 +251,9 @@ const InpaintingBoundingBoxPreview = () => {
onMouseDown={(e: KonvaEventObject<MouseEvent>) => {
e.cancelBubble = true;
}}
onMouseOver={(e: KonvaEventObject<MouseEvent>) => {
e.cancelBubble = true;
}}
anchorDragBoundFunc={(
oldPos: Vector2d, // old absolute position of anchor point
newPos: Vector2d, // new absolute position (potentially) of anchor point

View File

@ -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<boolean>(true);
const wasLastEventOverCanvas = useRef<boolean>(false);
const lastEvent = useRef<KeyboardEvent | null>(null);
@ -52,7 +57,8 @@ const KeyboardEventManager = () => {
!['Alt', ' '].includes(e.key) ||
activeTabName !== 'inpainting' ||
!shouldShowMask ||
e.repeat
e.repeat ||
shouldLockBoundingBox
) {
return;
}

View File

@ -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<boolean>) => {
state.shouldShowBoundingBoxFill = action.payload;
},
setIsBoundingBoxTransforming: (state, action: PayloadAction<boolean>) => {
state.isBoundingBoxTransforming = action.payload;
setIsTransformingBoundingBox: (state, action: PayloadAction<boolean>) => {
state.isTransformingBoundingBox = action.payload;
},
setIsDrawing: (state, action: PayloadAction<boolean>) => {
state.isDrawing = action.payload;
@ -329,6 +331,9 @@ export const inpaintingSlice = createSlice({
setInpaintReplace: (state, action: PayloadAction<number>) => {
state.inpaintReplace = action.payload;
},
setShouldLockBoundingBox: (state, action: PayloadAction<boolean>) => {
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;

View File

@ -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,
};
},