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 (
+
+
+
+
+
+
+ }
+ 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