From 710e465054dc8109484ab8d0b836d3f02823ae18 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Fri, 28 Oct 2022 02:26:28 +1300 Subject: [PATCH] Add Inpainting Settings - Enable and Disable Inpainting Box (with backend support) - Enable and Disable Bounding Box Darkening - Reset Bounding Box --- .../src/common/util/parameterTranslation.ts | 21 ++- .../Inpainting/BoundingBoxDimensions.scss | 13 -- .../Inpainting/BoundingBoxDimensions.tsx | 89 --------- .../Inpainting/BoundingBoxSettings.scss | 44 +++++ .../Inpainting/BoundingBoxSettings.tsx | 176 ++++++++++++++++++ .../Inpainting/InpaintingSettings.tsx | 59 ++++++ .../tabs/Inpainting/InpaintingCanvas.tsx | 5 +- .../tabs/Inpainting/InpaintingControls.tsx | 15 -- .../tabs/Inpainting/InpaintingPanel.tsx | 4 +- .../tabs/Inpainting/inpaintingSlice.ts | 11 ++ .../Inpainting/inpaintingSliceSelectors.ts | 2 + frontend/src/styles/index.scss | 2 +- 12 files changed, 315 insertions(+), 126 deletions(-) delete mode 100644 frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxDimensions.scss delete mode 100644 frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxDimensions.tsx create mode 100644 frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.scss create mode 100644 frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.tsx create mode 100644 frontend/src/features/options/AdvancedOptions/Inpainting/InpaintingSettings.tsx diff --git a/frontend/src/common/util/parameterTranslation.ts b/frontend/src/common/util/parameterTranslation.ts index a3038ee5fb..90d9adeb1f 100644 --- a/frontend/src/common/util/parameterTranslation.ts +++ b/frontend/src/common/util/parameterTranslation.ts @@ -101,13 +101,26 @@ export const frontendToBackendParameters = ( lines, boundingBoxCoordinate: { x, y }, boundingBoxDimensions: { width, height }, + shouldShowBoundingBox, } = inpaintingState; + let bx = x, + by = y, + bwidth = width, + bheight = height; + + if (!shouldShowBoundingBox) { + bx = 0; + by = 0; + bwidth = maskImageElement.width; + bheight = maskImageElement.height; + } + const boundingBox = { - x, - y, - width, - height, + x: bx, + y: by, + width: bwidth, + height: bheight, }; generationParameters.init_img = imageToProcessUrl; diff --git a/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxDimensions.scss b/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxDimensions.scss deleted file mode 100644 index 5368f0f474..0000000000 --- a/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxDimensions.scss +++ /dev/null @@ -1,13 +0,0 @@ -.inpainting-bounding-box-dimensions { - display: flex; - flex-direction: column; - row-gap: 1rem; - max-width: 100%; -} - -.inpainting-bounding-box-dimensions-slider-numberinput { - display: flex; - flex-direction: row; - column-gap: 0.5rem; - width: 100%; -} diff --git a/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxDimensions.tsx b/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxDimensions.tsx deleted file mode 100644 index b7823f88b3..0000000000 --- a/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxDimensions.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { FormLabel } from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import _ from 'lodash'; -import { - RootState, - useAppDispatch, - useAppSelector, -} from '../../../../app/store'; -import IAINumberInput from '../../../../common/components/IAINumberInput'; -import IAISlider from '../../../../common/components/IAISlider'; -import { roundDownToMultiple } from '../../../../common/util/roundDownToMultiple'; -import { - InpaintingState, - setBoundingBoxDimensions, -} from '../../../tabs/Inpainting/inpaintingSlice'; - -const boundingBoxDimensionsSelector = createSelector( - (state: RootState) => state.inpainting, - (inpainting: InpaintingState) => { - const { canvasDimensions, boundingBoxDimensions } = inpainting; - return { canvasDimensions, boundingBoxDimensions }; - }, - { - memoizeOptions: { - resultEqualityCheck: _.isEqual, - }, - } -); - -const BoundingBoxDimensions = () => { - const dispatch = useAppDispatch(); - const { canvasDimensions, boundingBoxDimensions } = useAppSelector( - boundingBoxDimensionsSelector - ); - - const handleChangeBoundingBoxWidth = (v: number) => { - dispatch(setBoundingBoxDimensions({ ...boundingBoxDimensions, width: v })); - }; - - const handleChangeBoundingBoxHeight = (v: number) => { - dispatch(setBoundingBoxDimensions({ ...boundingBoxDimensions, height: v })); - }; - - return ( -
- Inpainting Bounding Box -
- - -
-
- - -
-
- ); -}; - -export default BoundingBoxDimensions; diff --git a/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.scss b/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.scss new file mode 100644 index 0000000000..43127e291f --- /dev/null +++ b/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.scss @@ -0,0 +1,44 @@ +.inpainting-bounding-box-settings { + display: flex; + flex-direction: column; + max-width: 100%; + border-radius: 0.4rem; + border: 2px solid var(--tab-color); +} + +.inpainting-bounding-box-header { + background-color: var(--tab-color); + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 0.5rem 1rem; + border-radius: 0.4rem 0.4rem 0 0; + + p { + font-weight: bold; + } +} + +.inpainting-bounding-box-settings-items { + padding: 1rem; + display: flex; + flex-direction: column; + row-gap: 1rem; + + .inpainting-bounding-box-reset-icon-btn { + background-color: var(--btn-load-more) !important; + &:hover { + background-color: var(--btn-load-more-hover) !important; + } + } +} + +.inpainting-bounding-box-dimensions-slider-numberinput { + display: flex; + justify-content: space-between; + column-gap: 1rem; +} + +.inpainting-bounding-box-darken { + width: max-content; +} diff --git a/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.tsx b/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.tsx new file mode 100644 index 0000000000..755aee126d --- /dev/null +++ b/frontend/src/features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.tsx @@ -0,0 +1,176 @@ +import { createSelector } from '@reduxjs/toolkit'; +import _ from 'lodash'; +import { ChangeEvent } from 'react'; +import { BiReset } from 'react-icons/bi'; + +import { + RootState, + useAppDispatch, + useAppSelector, +} from '../../../../app/store'; +import IAICheckbox from '../../../../common/components/IAICheckbox'; +import IAIIconButton from '../../../../common/components/IAIIconButton'; + +import IAINumberInput from '../../../../common/components/IAINumberInput'; +import IAISlider from '../../../../common/components/IAISlider'; +import IAISwitch from '../../../../common/components/IAISwitch'; +import { roundDownToMultiple } from '../../../../common/util/roundDownToMultiple'; +import { + InpaintingState, + setBoundingBoxDimensions, + setShouldShowBoundingBox, + setShouldShowBoundingBoxFill, +} from '../../../tabs/Inpainting/inpaintingSlice'; + +const boundingBoxDimensionsSelector = createSelector( + (state: RootState) => state.inpainting, + (inpainting: InpaintingState) => { + const { + canvasDimensions, + boundingBoxDimensions, + shouldShowBoundingBox, + shouldShowBoundingBoxFill, + pastLines, + futureLines, + } = inpainting; + return { + canvasDimensions, + boundingBoxDimensions, + shouldShowBoundingBox, + shouldShowBoundingBoxFill, + pastLines, + futureLines, + }; + }, + { + memoizeOptions: { + resultEqualityCheck: _.isEqual, + }, + } +); + +const BoundingBoxSettings = () => { + const dispatch = useAppDispatch(); + const { + canvasDimensions, + boundingBoxDimensions, + shouldShowBoundingBox, + shouldShowBoundingBoxFill, + } = useAppSelector(boundingBoxDimensionsSelector); + + const handleChangeBoundingBoxWidth = (v: number) => { + dispatch(setBoundingBoxDimensions({ ...boundingBoxDimensions, width: v })); + }; + + const handleChangeBoundingBoxHeight = (v: number) => { + dispatch(setBoundingBoxDimensions({ ...boundingBoxDimensions, height: v })); + }; + + const handleShowBoundingBox = (e: ChangeEvent) => + dispatch(setShouldShowBoundingBox(e.target.checked)); + + const handleChangeShouldShowBoundingBoxFill = () => { + dispatch(setShouldShowBoundingBoxFill(!shouldShowBoundingBoxFill)); + }; + + const handleResetWidth = () => { + dispatch( + setBoundingBoxDimensions({ + ...boundingBoxDimensions, + width: canvasDimensions.width, + }) + ); + }; + + const handleResetHeight = () => { + dispatch( + setBoundingBoxDimensions({ + ...boundingBoxDimensions, + height: canvasDimensions.height, + }) + ); + }; + + return ( +
+
+

Inpaint Box

+ +
+
+
+ + + } + styleClass="inpainting-bounding-box-reset-icon-btn" + /> +
+
+ + + } + styleClass="inpainting-bounding-box-reset-icon-btn" + /> +
+ +
+
+ ); +}; + +export default BoundingBoxSettings; diff --git a/frontend/src/features/options/AdvancedOptions/Inpainting/InpaintingSettings.tsx b/frontend/src/features/options/AdvancedOptions/Inpainting/InpaintingSettings.tsx new file mode 100644 index 0000000000..a1282c080d --- /dev/null +++ b/frontend/src/features/options/AdvancedOptions/Inpainting/InpaintingSettings.tsx @@ -0,0 +1,59 @@ +import { useToast } from '@chakra-ui/react'; +import { createSelector } from '@reduxjs/toolkit'; +import React from 'react'; +import { + RootState, + useAppDispatch, + useAppSelector, +} from '../../../../app/store'; +import IAIButton from '../../../../common/components/IAIButton'; +import { + InpaintingState, + setClearBrushHistory, +} from '../../../tabs/Inpainting/inpaintingSlice'; +import BoundingBoxSettings from './BoundingBoxSettings'; +import _ from 'lodash'; + +const inpaintingSelector = createSelector( + (state: RootState) => state.inpainting, + (inpainting: InpaintingState) => { + const { pastLines, futureLines } = inpainting; + return { + pastLines, + futureLines, + }; + }, + { + memoizeOptions: { + resultEqualityCheck: _.isEqual, + }, + } +); + +export default function InpaintingSettings() { + const dispatch = useAppDispatch(); + const toast = useToast(); + + const { pastLines, futureLines } = useAppSelector(inpaintingSelector); + + const handleClearBrushHistory = () => { + dispatch(setClearBrushHistory()); + toast({ + title: 'Brush Stroke History Cleared', + status: 'success', + duration: 2500, + isClosable: true, + }); + }; + return ( + <> + + 0 || pastLines.length > 0 ? false : true} + /> + + ); +} diff --git a/frontend/src/features/tabs/Inpainting/InpaintingCanvas.tsx b/frontend/src/features/tabs/Inpainting/InpaintingCanvas.tsx index 39b16501ed..ff60baa216 100644 --- a/frontend/src/features/tabs/Inpainting/InpaintingCanvas.tsx +++ b/frontend/src/features/tabs/Inpainting/InpaintingCanvas.tsx @@ -61,6 +61,7 @@ const InpaintingCanvas = () => { shouldShowBoundingBoxFill, isDrawing, isBoundingBoxTransforming, + shouldShowBoundingBox, } = useAppSelector(inpaintingCanvasSelector); // set the closure'd refs @@ -280,10 +281,10 @@ const InpaintingCanvas = () => { )} - {shouldShowBoundingBoxFill && ( + {shouldShowBoundingBox && shouldShowBoundingBoxFill && ( )} - + {shouldShowBoundingBox && } diff --git a/frontend/src/features/tabs/Inpainting/InpaintingControls.tsx b/frontend/src/features/tabs/Inpainting/InpaintingControls.tsx index f7d510b4f6..569db6b684 100644 --- a/frontend/src/features/tabs/Inpainting/InpaintingControls.tsx +++ b/frontend/src/features/tabs/Inpainting/InpaintingControls.tsx @@ -6,8 +6,6 @@ import { FaPalette, FaPlus, FaRedo, - FaTint, - FaTintSlash, FaUndo, } from 'react-icons/fa'; import { BiHide, BiShow } from 'react-icons/bi'; @@ -25,7 +23,6 @@ import { setShouldShowMask, setShouldInvertMask, setNeedsRepaint, - setShouldShowBoundingBoxFill, } from './inpaintingSlice'; import { MdInvertColors, MdInvertColorsOff } from 'react-icons/md'; @@ -49,7 +46,6 @@ const InpaintingControls = () => { isMaskEmpty, activeTabName, showDualDisplay, - shouldShowBoundingBoxFill, } = useAppSelector(inpaintingControlsSelector); const dispatch = useAppDispatch(); @@ -268,10 +264,6 @@ const InpaintingControls = () => { dispatch(setNeedsRepaint(true)); }; - const handleChangeShouldShowBoundingBoxFill = () => { - dispatch(setShouldShowBoundingBoxFill(!shouldShowBoundingBoxFill)); - }; - return (
@@ -390,13 +382,6 @@ const InpaintingControls = () => { data-selected={showDualDisplay} onClick={handleDualDisplay} /> - : } - data-selected={shouldShowBoundingBoxFill} - onClick={handleChangeShouldShowBoundingBoxFill} - />
diff --git a/frontend/src/features/tabs/Inpainting/InpaintingPanel.tsx b/frontend/src/features/tabs/Inpainting/InpaintingPanel.tsx index 9ff636da09..3f30f67f78 100644 --- a/frontend/src/features/tabs/Inpainting/InpaintingPanel.tsx +++ b/frontend/src/features/tabs/Inpainting/InpaintingPanel.tsx @@ -3,7 +3,7 @@ import { RootState, useAppSelector } from '../../../app/store'; import FaceRestoreHeader from '../../options/AdvancedOptions/FaceRestore/FaceRestoreHeader'; import FaceRestoreOptions from '../../options/AdvancedOptions/FaceRestore/FaceRestoreOptions'; import ImageToImageStrength from '../../options/AdvancedOptions/ImageToImage/ImageToImageStrength'; -import BoundingBoxDimensions from '../../options/AdvancedOptions/Inpainting/BoundingBoxDimensions'; +import InpaintingSettings from '../../options/AdvancedOptions/Inpainting/InpaintingSettings'; import SeedHeader from '../../options/AdvancedOptions/Seed/SeedHeader'; import SeedOptions from '../../options/AdvancedOptions/Seed/SeedOptions'; import UpscaleHeader from '../../options/AdvancedOptions/Upscale/UpscaleHeader'; @@ -49,11 +49,11 @@ export default function InpaintingPanel() { - + {showAdvancedOptions ? ( diff --git a/frontend/src/features/tabs/Inpainting/inpaintingSlice.ts b/frontend/src/features/tabs/Inpainting/inpaintingSlice.ts index 75d9e9f4a9..d998d24ccb 100644 --- a/frontend/src/features/tabs/Inpainting/inpaintingSlice.ts +++ b/frontend/src/features/tabs/Inpainting/inpaintingSlice.ts @@ -38,6 +38,7 @@ export interface InpaintingState { boundingBoxCoordinate: Vector2d; isMovingBoundingBox: boolean; boundingBoxPreviewFill: RgbaColor; + shouldShowBoundingBox: boolean; shouldShowBoundingBoxFill: boolean; isBoundingBoxTransforming: boolean; lines: MaskLine[]; @@ -62,6 +63,7 @@ const initialInpaintingState: InpaintingState = { boundingBoxDimensions: { width: 64, height: 64 }, boundingBoxCoordinate: { x: 0, y: 0 }, boundingBoxPreviewFill: { r: 0, g: 0, b: 0, a: 0.7 }, + shouldShowBoundingBox: false, shouldShowBoundingBoxFill: false, isBoundingBoxTransforming: false, cursorPosition: null, @@ -310,6 +312,13 @@ export const inpaintingSlice = createSlice({ setIsDrawing: (state, action: PayloadAction) => { state.isDrawing = action.payload; }, + setShouldShowBoundingBox: (state, action: PayloadAction) => { + state.shouldShowBoundingBox = action.payload; + }, + setClearBrushHistory: (state) => { + state.pastLines = []; + state.futureLines = []; + }, }, }); @@ -341,6 +350,8 @@ export const { setIsBoundingBoxTransforming, setIsDrawing, setShouldShowBrush, + setShouldShowBoundingBox, + setClearBrushHistory, } = 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 50c17ef540..65dcd29311 100644 --- a/frontend/src/features/tabs/Inpainting/inpaintingSliceSelectors.ts +++ b/frontend/src/features/tabs/Inpainting/inpaintingSliceSelectors.ts @@ -79,6 +79,7 @@ export const inpaintingCanvasSelector = createSelector( shouldShowBoundingBoxFill, isDrawing, isBoundingBoxTransforming, + shouldShowBoundingBox, } = inpainting; return { tool, @@ -97,6 +98,7 @@ export const inpaintingCanvasSelector = createSelector( shouldShowBoundingBoxFill, isDrawing, isBoundingBoxTransforming, + shouldShowBoundingBox, }; }, { diff --git a/frontend/src/styles/index.scss b/frontend/src/styles/index.scss index 24556a8ce2..43d2ea931c 100644 --- a/frontend/src/styles/index.scss +++ b/frontend/src/styles/index.scss @@ -22,7 +22,7 @@ @use '../features/options/MainOptions/MainOptions.scss'; @use '../features/options/AccordionItems/AdvancedSettings.scss'; @use '../features/options/AdvancedOptions/Upscale/UpscaleOptions.scss'; -@use '../features/options/AdvancedOptions/Inpainting/BoundingBoxDimensions.scss'; +@use '../features/options/AdvancedOptions/Inpainting/BoundingBoxSettings.scss'; @use '../features/system/ProgressBar.scss'; // gallery