Fixes inpainting + code cleanup

This commit is contained in:
psychedelicious 2022-11-12 00:06:26 +11:00 committed by blessedcoolant
parent 00385240e7
commit e21e901fa2
31 changed files with 715 additions and 762 deletions

View File

@ -698,22 +698,24 @@ class InvokeAIWebServer:
So we need to convert each into a PIL Image.
"""
init_img_url = generation_parameters["init_img"]
truncated_outpaint_mask_b64 = generation_parameters["init_mask"][:64]
init_img_url = generation_parameters["init_img"]
init_img_url = generation_parameters["init_img"]
init_img_path = self.get_image_path_from_url(init_img_url)
original_image = Image.open(init_img_path)
rgba_image = original_image.convert("RGBA")
# copy a region from it which we will inpaint
cropped_init_image = copy_image_from_bounding_box(
rgba_image, **generation_parameters["bounding_box"]
)
original_bounding_box = generation_parameters["bounding_box"].copy()
generation_parameters["init_img"] = cropped_init_image
# Convert mask dataURL to an image and convert to greyscale

File diff suppressed because one or more lines are too long

593
frontend/dist/assets/index.ece4fb83.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -7,6 +7,7 @@
<title>InvokeAI - A Stable Diffusion Toolkit</title>
<link rel="shortcut icon" type="icon" href="./assets/favicon.0d253ced.ico" />
<<<<<<< refs/remotes/upstream/development
<<<<<<< refs/remotes/upstream/development
<<<<<<< refs/remotes/upstream/development
<script type="module" crossorigin src="./assets/index.a8ba2a6c.js"></script>
<link rel="stylesheet" href="./assets/index.40a72c80.css">
@ -15,6 +16,9 @@
=======
<script type="module" crossorigin src="./assets/index.a06633cf.js"></script>
>>>>>>> Builds fresh bundle
=======
<script type="module" crossorigin src="./assets/index.ece4fb83.js"></script>
>>>>>>> Fixes inpainting + code cleanup
<link rel="stylesheet" href="./assets/index.a44a1287.css">
>>>>>>> Builds fresh bundle
</head>

View File

@ -1,9 +1,6 @@
import { useEffect } from 'react';
import ProgressBar from 'features/system/ProgressBar';
import SiteHeader from 'features/system/SiteHeader';
import Console from 'features/system/Console';
import { useAppDispatch } from './store';
import { requestSystemConfig } from './socketio/actions';
import { keepGUIAlive } from './utils';
import InvokeTabs from 'features/tabs/InvokeTabs';
import ImageUploader from 'common/components/ImageUploader';
@ -80,8 +77,6 @@ const appSelector = createSelector(
);
const App = () => {
const dispatch = useAppDispatch();
const { shouldShowGalleryButton, shouldShowOptionsPanelButton } =
useAppSelector(appSelector);

View File

@ -17,7 +17,6 @@ import {
modelChangeRequested,
setIsProcessing,
} from 'features/system/systemSlice';
import { inpaintingImageElementRef } from 'features/canvas/IAICanvas';
import { InvokeTabName } from 'features/tabs/InvokeTabs';
import * as InvokeAI from 'app/invokeai';
import { RootState } from 'app/store';
@ -57,9 +56,9 @@ const makeSocketIOEmitters = (
if (['inpainting', 'outpainting'].includes(generationMode)) {
const baseCanvasImage = baseCanvasImageSelector(getState());
const imageUrl = baseCanvasImage?.url;
const imageUrl = baseCanvasImage?.image.url;
if (!inpaintingImageElementRef.current || !imageUrl) {
if (!imageUrl) {
dispatch(
addLogEntry({
timestamp: dateFormat(new Date(), 'isoDateTime'),
@ -72,9 +71,6 @@ const makeSocketIOEmitters = (
}
frontendToBackendParametersConfig.imageToProcessUrl = imageUrl;
// frontendToBackendParametersConfig.maskImageElement =
// inpaintingImageElementRef.current;
} else if (!['txt2img', 'img2img'].includes(generationMode)) {
if (!galleryState.currentImage?.url) return;

View File

@ -32,12 +32,14 @@ import {
setInitialImage,
setMaskPath,
} from 'features/options/optionsSlice';
import { requestImages, requestNewImages, requestSystemConfig } from './actions';
import {
requestImages,
requestNewImages,
requestSystemConfig,
} from './actions';
import {
addImageToOutpaintingSesion,
clearImageToInpaint,
setImageToInpaint,
setImageToOutpaint,
} from 'features/canvas/canvasSlice';
import { tabMap } from 'features/tabs/InvokeTabs';
@ -312,16 +314,11 @@ const makeSocketIOListeners = (
// remove references to image in options
const { initialImage, maskPath } = getState().options;
const { inpainting, outpainting } = getState().canvas;
if (initialImage?.url === url || initialImage === url) {
dispatch(clearInitialImage());
}
// if (imageToInpaint?.url === url) {
// dispatch(clearImageToInpaint());
// }
if (maskPath === url) {
dispatch(setMaskPath(''));
}

View File

@ -1,5 +1,4 @@
import { Heading } from '@chakra-ui/react';
import { KeyboardEvent } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
type ImageUploadOverlayProps = {

View File

@ -1,15 +1,13 @@
// lib
import { MutableRefObject, useEffect, useRef, useState } from 'react';
import { MutableRefObject, useRef } from 'react';
import Konva from 'konva';
import { Layer, Stage } from 'react-konva';
import { Image as KonvaImage } from 'react-konva';
import { Stage as StageType } from 'konva/lib/Stage';
// app
import { useAppDispatch, useAppSelector } from 'app/store';
import { useAppSelector } from 'app/store';
import {
baseCanvasImageSelector,
clearImageToInpaint,
currentCanvasSelector,
outpaintingCanvasSelector,
} from 'features/canvas/canvasSlice';
@ -18,8 +16,7 @@ import {
import IAICanvasMaskLines from './IAICanvasMaskLines';
import IAICanvasBrushPreview from './IAICanvasBrushPreview';
import { Vector2d } from 'konva/lib/types';
import IAICanvasBoundingBoxPreview from './IAICanvasBoundingBoxPreview';
import { useToast } from '@chakra-ui/react';
import IAICanvasBoundingBox from './IAICanvasBoundingBox';
import useCanvasHotkeys from './hooks/useCanvasHotkeys';
import _ from 'lodash';
import { createSelector } from '@reduxjs/toolkit';
@ -32,7 +29,7 @@ import useCanvasMouseMove from './hooks/useCanvasMouseMove';
import useCanvasMouseEnter from './hooks/useCanvasMouseEnter';
import useCanvasMouseOut from './hooks/useCanvasMouseOut';
import useCanvasDragMove from './hooks/useCanvasDragMove';
import IAICanvasOutpaintingObjects from './IAICanvasOutpaintingObjects';
import IAICanvasObjectRenderer from './IAICanvasObjectRenderer';
import IAICanvasGrid from './IAICanvasGrid';
import IAICanvasIntermediateImage from './IAICanvasIntermediateImage';
import IAICanvasStatusText from './IAICanvasStatusText';
@ -46,18 +43,14 @@ const canvasSelector = createSelector(
],
(currentCanvas, outpaintingCanvas, baseCanvasImage, activeTabName) => {
const {
shouldInvertMask,
isMaskEnabled,
shouldShowCheckboardTransparency,
stageScale,
shouldShowBoundingBox,
shouldLockBoundingBox,
isTransformingBoundingBox,
isMouseOverBoundingBox,
isMovingBoundingBox,
stageDimensions,
stageCoordinates,
isMoveStageKeyHeld,
tool,
isMovingStage,
} = currentCanvas;
@ -71,7 +64,7 @@ const canvasSelector = createSelector(
stageCursor = undefined;
} else if (isMouseOverBoundingBox) {
stageCursor = 'move';
} else {
} else if (activeTabName === 'outpainting') {
if (isMovingStage) {
stageCursor = 'grabbing';
} else {
@ -83,22 +76,15 @@ const canvasSelector = createSelector(
}
return {
shouldInvertMask,
isMaskEnabled,
shouldShowCheckboardTransparency,
stageScale,
shouldShowBoundingBox,
shouldLockBoundingBox,
shouldShowGrid,
isTransformingBoundingBox,
isModifyingBoundingBox: isTransformingBoundingBox || isMovingBoundingBox,
stageCursor,
isMouseOverBoundingBox,
stageDimensions,
stageCoordinates,
isMoveStageKeyHeld,
activeTabName,
baseCanvasImage,
isMaskEnabled,
isModifyingBoundingBox: isTransformingBoundingBox || isMovingBoundingBox,
shouldShowBoundingBox,
shouldShowGrid,
stageCoordinates,
stageCursor,
stageDimensions,
stageScale,
tool,
};
},
@ -112,45 +98,32 @@ const canvasSelector = createSelector(
// Use a closure allow other components to use these things... not ideal...
export let stageRef: MutableRefObject<StageType | null>;
export let canvasImageLayerRef: MutableRefObject<Konva.Layer | null>;
export let inpaintingImageElementRef: MutableRefObject<HTMLImageElement | null>;
const IAICanvas = () => {
const dispatch = useAppDispatch();
const {
shouldInvertMask,
activeTabName,
isMaskEnabled,
shouldShowCheckboardTransparency,
stageScale,
shouldShowBoundingBox,
isModifyingBoundingBox,
shouldShowBoundingBox,
shouldShowGrid,
stageCoordinates,
stageCursor,
stageDimensions,
stageCoordinates,
shouldShowGrid,
activeTabName,
baseCanvasImage,
stageScale,
tool,
} = useAppSelector(canvasSelector);
useCanvasHotkeys();
const toast = useToast();
// set the closure'd refs
stageRef = useRef<StageType>(null);
canvasImageLayerRef = useRef<Konva.Layer>(null);
inpaintingImageElementRef = useRef<HTMLImageElement>(null);
const lastCursorPositionRef = useRef<Vector2d>({ x: 0, y: 0 });
// Use refs for values that do not affect rendering, other values in redux
const didMouseMoveRef = useRef<boolean>(false);
// Load the image into this
const [canvasBgImage, setCanvasBgImage] = useState<HTMLImageElement | null>(
null
);
const handleWheel = useCanvasWheel(stageRef);
const handleMouseDown = useCanvasMouseDown(stageRef);
const handleMouseUp = useCanvasMouseUp(stageRef, didMouseMoveRef);
@ -164,29 +137,6 @@ const IAICanvas = () => {
const { handleDragStart, handleDragMove, handleDragEnd } =
useCanvasDragMove();
// Load the image and set the options panel width & height
useEffect(() => {
if (baseCanvasImage) {
const image = new Image();
image.onload = () => {
inpaintingImageElementRef.current = image;
setCanvasBgImage(image);
};
image.onerror = () => {
toast({
title: 'Unable to Load Image',
description: `Image ${baseCanvasImage.url} failed to load`,
status: 'error',
isClosable: true,
});
dispatch(clearImageToInpaint());
};
image.src = baseCanvasImage.url;
} else {
setCanvasBgImage(null);
}
}, [baseCanvasImage, dispatch, stageScale, toast]);
return (
<div className="inpainting-canvas-container">
<div className="inpainting-canvas-wrapper">
@ -209,36 +159,31 @@ const IAICanvas = () => {
onDragMove={handleDragMove}
onDragEnd={handleDragEnd}
onWheel={handleWheel}
listening={
tool === 'move' &&
!isModifyingBoundingBox &&
activeTabName === 'outpainting'
}
listening={tool === 'move' && !isModifyingBoundingBox}
draggable={
tool === 'move' &&
!isModifyingBoundingBox &&
activeTabName === 'outpainting'
}
>
<Layer visible={shouldShowGrid}>
<Layer id={'grid'} visible={shouldShowGrid}>
<IAICanvasGrid />
</Layer>
<Layer
id={'image-layer'}
id={'image'}
ref={canvasImageLayerRef}
listening={false}
imageSmoothingEnabled={false}
>
<IAICanvasOutpaintingObjects />
<IAICanvasObjectRenderer />
<IAICanvasIntermediateImage />
</Layer>
<Layer id={'mask-layer'} visible={isMaskEnabled} listening={false}>
<Layer id={'mask'} visible={isMaskEnabled} listening={false}>
<IAICanvasMaskLines visible={true} listening={false} />
<IAICanvasMaskCompositer listening={false} />
{canvasBgImage && (
{/* {canvasBgImage && (
<>
<KonvaImage
image={canvasBgImage}
@ -256,10 +201,10 @@ const IAICanvas = () => {
}
/>
</>
)}
)} */}
</Layer>
<Layer id={'preview-layer'}>
<IAICanvasBoundingBoxPreview visible={shouldShowBoundingBox} />
<Layer id={'tool'}>
<IAICanvasBoundingBox visible={shouldShowBoundingBox} />
<IAICanvasBrushPreview
visible={tool !== 'move'}
listening={false}

View File

@ -1,6 +1,5 @@
import { createSelector } from '@reduxjs/toolkit';
import Konva from 'konva';
import { Context } from 'konva/lib/Context';
import { KonvaEventObject } from 'konva/lib/Node';
import { Box } from 'konva/lib/shapes/Transformer';
import { Vector2d } from 'konva/lib/types';
@ -33,7 +32,6 @@ const boundingBoxPreviewSelector = createSelector(
boundingBoxDimensions,
stageDimensions,
stageScale,
shouldLockBoundingBox,
isDrawing,
isTransformingBoundingBox,
isMovingBoundingBox,
@ -52,7 +50,6 @@ const boundingBoxPreviewSelector = createSelector(
shouldDarkenOutsideBoundingBox,
isMovingBoundingBox,
isTransformingBoundingBox,
shouldLockBoundingBox,
stageDimensions,
stageScale,
baseCanvasImage,
@ -72,9 +69,7 @@ const boundingBoxPreviewSelector = createSelector(
type IAICanvasBoundingBoxPreviewProps = GroupConfig;
const IAICanvasBoundingBoxPreview = (
props: IAICanvasBoundingBoxPreviewProps
) => {
const IAICanvasBoundingBox = (props: IAICanvasBoundingBoxPreviewProps) => {
const { ...rest } = props;
const dispatch = useAppDispatch();
@ -86,7 +81,6 @@ const IAICanvasBoundingBoxPreview = (
shouldDarkenOutsideBoundingBox,
isMovingBoundingBox,
isTransformingBoundingBox,
shouldLockBoundingBox,
stageCoordinates,
stageDimensions,
stageScale,
@ -104,7 +98,7 @@ const IAICanvasBoundingBoxPreview = (
if (!transformerRef.current || !shapeRef.current) return;
transformerRef.current.nodes([shapeRef.current]);
transformerRef.current.getLayer()?.batchDraw();
}, [shouldLockBoundingBox]);
}, []);
const scaledStep = 64 * stageScale;
@ -264,7 +258,6 @@ const IAICanvasBoundingBoxPreview = (
[scaledStep]
);
// OK
const boundBoxFunc = useCallback(
(oldBoundBox: Box, newBoundBox: Box) => {
/**
@ -341,10 +334,10 @@ const IAICanvasBoundingBoxPreview = (
dragBoundFunc={
activeTabName === 'inpainting' ? dragBoundFunc : undefined
}
listening={!isDrawing && tool === 'move'}
draggable={true}
fillEnabled={tool === 'move'}
height={boundingBoxDimensions.height}
listening={!isDrawing && tool === 'move'}
onDragEnd={handleEndedModifying}
onDragMove={handleOnDragMove}
onMouseDown={handleStartedMoving}
@ -387,4 +380,4 @@ const IAICanvasBoundingBoxPreview = (
);
};
export default IAICanvasBoundingBoxPreview;
export default IAICanvasBoundingBox;

View File

@ -15,7 +15,6 @@ import IAIPopover from 'common/components/IAIPopover';
import IAIColorPicker from 'common/components/IAIColorPicker';
import IAISlider from 'common/components/IAISlider';
import { Flex } from '@chakra-ui/react';
import IAINumberInput from 'common/components/IAINumberInput';
export const selector = createSelector(
[currentCanvasSelector, outpaintingCanvasSelector, activeTabNameSelector],

View File

@ -2,7 +2,7 @@ import IAICanvasBrushControl from './IAICanvasControls/IAICanvasBrushControl';
import IAICanvasEraserControl from './IAICanvasControls/IAICanvasEraserControl';
import IAICanvasUndoControl from './IAICanvasControls/IAICanvasUndoButton';
import IAICanvasRedoControl from './IAICanvasControls/IAICanvasRedoButton';
import { Button, ButtonGroup } from '@chakra-ui/react';
import { ButtonGroup } from '@chakra-ui/react';
import IAICanvasMaskClear from './IAICanvasControls/IAICanvasMaskControls/IAICanvasMaskClear';
import IAICanvasMaskVisibilityControl from './IAICanvasControls/IAICanvasMaskControls/IAICanvasMaskVisibilityControl';
import IAICanvasMaskInvertControl from './IAICanvasControls/IAICanvasMaskControls/IAICanvasMaskInvertControl';
@ -11,8 +11,6 @@ import IAICanvasShowHideBoundingBoxControl from './IAICanvasControls/IAICanvasSh
import ImageUploaderIconButton from 'common/components/ImageUploaderIconButton';
import { createSelector } from '@reduxjs/toolkit';
import {
currentCanvasSelector,
GenericCanvasState,
outpaintingCanvasSelector,
OutpaintingCanvasState,
uploadOutpaintingMergedImage,
@ -23,7 +21,6 @@ import { OptionsState } from 'features/options/optionsSlice';
import _ from 'lodash';
import IAICanvasImageEraserControl from './IAICanvasControls/IAICanvasImageEraserControl';
import { canvasImageLayerRef } from './IAICanvas';
import { uploadImage } from 'app/socketio/actions';
import IAIIconButton from 'common/components/IAIIconButton';
import { FaSave } from 'react-icons/fa';
@ -56,12 +53,7 @@ export const canvasControlsSelector = createSelector(
const IAICanvasControls = () => {
const dispatch = useAppDispatch();
const {
activeTabName,
boundingBoxCoordinates,
boundingBoxDimensions,
stageScale,
} = useAppSelector(canvasControlsSelector);
const { activeTabName } = useAppSelector(canvasControlsSelector);
return (
<div className="inpainting-settings">

View File

@ -42,7 +42,7 @@ const IAICanvasIntermediateImage = (props: Props) => {
const {
boundingBox: { x, y, width, height },
} = intermediateImage;
return loadedImageElement ? (
<KonvaImage
x={x}

View File

@ -1,7 +1,6 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store';
import { RectConfig } from 'konva/lib/shapes/Rect';
import _ from 'lodash';
import { Rect } from 'react-konva';
import {
currentCanvasSelector,
@ -24,7 +23,6 @@ export const canvasMaskCompositerSelector = createSelector(
stageDimensions,
stageScale,
maskColorString: rgbaColorToString(maskColor),
maskOpacity: maskColor.a,
};
}
);
@ -116,13 +114,8 @@ const getColoredSVG = (color: string) => {
const IAICanvasMaskCompositer = (props: IAICanvasMaskCompositerProps) => {
const { ...rest } = props;
const {
maskColorString,
maskOpacity,
stageCoordinates,
stageDimensions,
stageScale,
} = useAppSelector(canvasMaskCompositerSelector);
const { maskColorString, stageCoordinates, stageDimensions, stageScale } =
useAppSelector(canvasMaskCompositerSelector);
const [fillPatternImage, setFillPatternImage] =
useState<HTMLImageElement | null>(null);

View File

@ -1,9 +1,9 @@
import { createSelector } from '@reduxjs/toolkit';
import { RootState, useAppSelector } from 'app/store';
import { useAppSelector } from 'app/store';
import _ from 'lodash';
import { Group, Line } from 'react-konva';
import {
CanvasState,
currentCanvasSelector,
isCanvasBaseImage,
isCanvasBaseLine,
} from './canvasSlice';
@ -11,14 +11,9 @@ import IAICanvasImage from './IAICanvasImage';
import { rgbaColorToString } from './util/colorToString';
const selector = createSelector(
[(state: RootState) => state.canvas],
(canvas: CanvasState) => {
return {
objects:
canvas.currentCanvas === 'outpainting'
? canvas.outpainting.objects
: undefined,
};
[currentCanvasSelector],
(currentCanvas) => {
return currentCanvas.objects;
},
{
memoizeOptions: {
@ -27,8 +22,8 @@ const selector = createSelector(
}
);
const IAICanvasOutpaintingObjects = () => {
const { objects } = useAppSelector(selector);
const IAICanvasObjectRenderer = () => {
const objects = useAppSelector(selector);
if (!objects) return null;
@ -62,4 +57,4 @@ const IAICanvasOutpaintingObjects = () => {
);
};
export default IAICanvasOutpaintingObjects;
export default IAICanvasObjectRenderer;

View File

@ -5,14 +5,10 @@ import { activeTabNameSelector } from 'features/options/optionsSelectors';
import {
baseCanvasImageSelector,
CanvasState,
currentCanvasSelector,
GenericCanvasState,
setStageDimensions,
setStageScale,
} from 'features/canvas/canvasSlice';
import { createSelector } from '@reduxjs/toolkit';
import * as InvokeAI from 'app/invokeai';
import { first } from 'lodash';
const canvasResizerSelector = createSelector(
(state: RootState) => state.canvas,
@ -39,13 +35,12 @@ const IAICanvasResizer = () => {
useLayoutEffect(() => {
window.setTimeout(() => {
if (!ref.current || !baseCanvasImage) return;
const width = ref.current.clientWidth;
const height = ref.current.clientHeight;
const { width: imageWidth, height: imageHeight } = baseCanvasImage.image;
const { clientWidth, clientHeight } = ref.current;
const scale = Math.min(
1,
Math.min(width / baseCanvasImage.width, height / baseCanvasImage.height)
Math.min(clientWidth / imageWidth, clientHeight / imageHeight)
);
dispatch(setStageScale(scale));
@ -53,15 +48,15 @@ const IAICanvasResizer = () => {
if (activeTabName === 'inpainting') {
dispatch(
setStageDimensions({
width: Math.floor(baseCanvasImage.width * scale),
height: Math.floor(baseCanvasImage.height * scale),
width: Math.floor(imageWidth * scale),
height: Math.floor(imageHeight * scale),
})
);
} else if (activeTabName === 'outpainting') {
dispatch(
setStageDimensions({
width: Math.floor(width),
height: Math.floor(height),
width: Math.floor(clientWidth),
height: Math.floor(clientHeight),
})
);
}

View File

@ -11,7 +11,6 @@ import * as InvokeAI from 'app/invokeai';
import _ from 'lodash';
import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
import { RootState } from 'app/store';
import { activeTabNameSelector } from 'features/options/optionsSelectors';
import { MutableRefObject } from 'react';
import Konva from 'konva';
@ -137,7 +136,7 @@ const initialGenericCanvasState: GenericCanvasState = {
tool: 'brush',
brushColor: { r: 90, g: 90, b: 255, a: 1 },
brushSize: 50,
maskColor: { r: 255, g: 90, b: 90, a: 0.5 },
maskColor: { r: 255, g: 90, b: 90, a: 1 },
eraserSize: 50,
stageDimensions: { width: 0, height: 0 },
stageCoordinates: { x: 0, y: 0 },
@ -351,7 +350,16 @@ export const canvasSlice = createSlice({
state.inpainting.boundingBoxDimensions = newDimensions;
state.inpainting.boundingBoxCoordinates = newCoordinates;
state.inpainting.imageToInpaint = action.payload;
// state.inpainting.imageToInpaint = action.payload;
state.inpainting.objects = [
{
kind: 'image',
layer: 'base',
x: 0,
y: 0,
image: action.payload,
},
];
state.doesCanvasNeedScaling = true;
},
setStageDimensions: (state, action: PayloadAction<Dimensions>) => {
@ -567,19 +575,19 @@ export const canvasSlice = createSlice({
lastLine.points.push(...action.payload);
},
undo: (state) => {
if (state.outpainting.objects.length === 0) return;
if (state[state.currentCanvas].objects.length === 0) return;
const newObjects = state.outpainting.pastObjects.pop();
const newObjects = state[state.currentCanvas].pastObjects.pop();
if (!newObjects) return;
state.outpainting.futureObjects.unshift(state.outpainting.objects);
state.outpainting.objects = newObjects;
state[state.currentCanvas].futureObjects.unshift(state[state.currentCanvas].objects);
state[state.currentCanvas].objects = newObjects;
},
redo: (state) => {
if (state.outpainting.futureObjects.length === 0) return;
const newObjects = state.outpainting.futureObjects.shift();
if (state[state.currentCanvas].futureObjects.length === 0) return;
const newObjects = state[state.currentCanvas].futureObjects.shift();
if (!newObjects) return;
state.outpainting.pastObjects.push(state.outpainting.objects);
state.outpainting.objects = newObjects;
state[state.currentCanvas].pastObjects.push(state[state.currentCanvas].objects);
state[state.currentCanvas].objects = newObjects;
},
setShouldShowGrid: (state, action: PayloadAction<boolean>) => {
state.outpainting.shouldShowGrid = action.payload;
@ -748,17 +756,8 @@ export const inpaintingCanvasSelector = (
): InpaintingCanvasState => state.canvas.inpainting;
export const baseCanvasImageSelector = createSelector(
[(state: RootState) => state.canvas, activeTabNameSelector],
(canvas: CanvasState, activeTabName) => {
if (activeTabName === 'inpainting') {
return canvas.inpainting.imageToInpaint;
} else if (activeTabName === 'outpainting') {
const firstImageObject = canvas.outpainting.objects.find(
(obj) => obj.kind === 'image'
);
if (firstImageObject && firstImageObject.kind === 'image') {
return firstImageObject.image;
}
}
[currentCanvasSelector],
(currentCanvas) => {
return currentCanvas.objects.find(isCanvasBaseImage);
}
);

View File

@ -2,26 +2,20 @@ import { createSelector } from '@reduxjs/toolkit';
import _ from 'lodash';
import { useHotkeys } from 'react-hotkeys-hook';
import { activeTabNameSelector } from 'features/options/optionsSelectors';
import { OptionsState } from 'features/options/optionsSlice';
import {
CanvasTool,
setShouldShowBoundingBox,
setTool,
toggleShouldLockBoundingBox,
} from 'features/canvas/canvasSlice';
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
import { currentCanvasSelector, GenericCanvasState } from '../canvasSlice';
import { useAppDispatch, useAppSelector } from 'app/store';
import { currentCanvasSelector } from '../canvasSlice';
import { useRef } from 'react';
const inpaintingCanvasHotkeysSelector = createSelector(
[
(state: RootState) => state.options,
currentCanvasSelector,
activeTabNameSelector,
],
(options: OptionsState, currentCanvas: GenericCanvasState, activeTabName) => {
[currentCanvasSelector, activeTabNameSelector],
(currentCanvas, activeTabName) => {
const {
isMaskEnabled,
cursorPosition,
shouldLockBoundingBox,
shouldShowBoundingBox,
@ -30,7 +24,6 @@ const inpaintingCanvasHotkeysSelector = createSelector(
return {
activeTabName,
isMaskEnabled,
isCursorOnCanvas: Boolean(cursorPosition),
shouldLockBoundingBox,
shouldShowBoundingBox,
@ -46,8 +39,9 @@ const inpaintingCanvasHotkeysSelector = createSelector(
const useInpaintingCanvasHotkeys = () => {
const dispatch = useAppDispatch();
const { isMaskEnabled, activeTabName, shouldShowBoundingBox, tool } =
useAppSelector(inpaintingCanvasHotkeysSelector);
const { activeTabName, shouldShowBoundingBox, tool } = useAppSelector(
inpaintingCanvasHotkeysSelector
);
const previousToolRef = useRef<CanvasTool | null>(null);
// Toggle lock bounding box

View File

@ -1,5 +1,4 @@
import { useAppDispatch } from 'app/store';
import _ from 'lodash';
import { useCallback } from 'react';
import { setCursorPosition, setIsDrawing } from '../canvasSlice';

View File

@ -21,7 +21,7 @@ import IAIIconButton from 'common/components/IAIIconButton';
import UpscaleOptions from 'features/options/AdvancedOptions/Upscale/UpscaleOptions';
import FaceRestoreOptions from 'features/options/AdvancedOptions/FaceRestore/FaceRestoreOptions';
import { useHotkeys } from 'react-hotkeys-hook';
import { ButtonGroup, Link, useClipboard, useToast } from '@chakra-ui/react';
import { ButtonGroup, Link, useToast } from '@chakra-ui/react';
import {
FaAsterisk,
FaCode,

View File

@ -1,4 +1,4 @@
import { IconButton, Image, Spinner } from '@chakra-ui/react';
import { IconButton, Image } from '@chakra-ui/react';
import { useState } from 'react';
import { FaAngleLeft, FaAngleRight } from 'react-icons/fa';
import { RootState, useAppDispatch, useAppSelector } from 'app/store';

View File

@ -1,5 +1,5 @@
import React from 'react';
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/store';
import IAICheckbox from 'common/components/IAICheckbox';
import {
currentCanvasSelector,

View File

@ -1,12 +1,10 @@
import React from 'react';
import IAISlider from 'common/components/IAISlider';
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/store';
import { createSelector } from '@reduxjs/toolkit';
import {
currentCanvasSelector,
GenericCanvasState,
// InpaintingState,
setBoundingBoxDimensions,
} from 'features/canvas/canvasSlice';
@ -15,7 +13,7 @@ import _ from 'lodash';
const boundingBoxDimensionsSelector = createSelector(
currentCanvasSelector,
(currentCanvas: GenericCanvasState) => {
(currentCanvas) => {
const { stageDimensions, boundingBoxDimensions, shouldLockBoundingBox } =
currentCanvas;
return {

View File

@ -1,16 +1,15 @@
import React from 'react';
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/store';
import IAICheckbox from 'common/components/IAICheckbox';
import {
currentCanvasSelector,
GenericCanvasState,
setShouldLockBoundingBox,
} from 'features/canvas/canvasSlice';
import { createSelector } from '@reduxjs/toolkit';
const boundingBoxLockSelector = createSelector(
currentCanvasSelector,
(currentCanvas: GenericCanvasState) => currentCanvas.shouldLockBoundingBox
(currentCanvas) => currentCanvas.shouldLockBoundingBox
);
export default function BoundingBoxLock() {

View File

@ -1,17 +1,16 @@
import React from 'react';
import { BiHide, BiShow } from 'react-icons/bi';
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/store';
import IAIIconButton from 'common/components/IAIIconButton';
import {
currentCanvasSelector,
GenericCanvasState,
setShouldShowBoundingBox,
} from 'features/canvas/canvasSlice';
import { createSelector } from '@reduxjs/toolkit';
const boundingBoxVisibilitySelector = createSelector(
currentCanvasSelector,
(currentCanvas: GenericCanvasState) => currentCanvas.shouldShowBoundingBox
(currentCanvas) => currentCanvas.shouldShowBoundingBox
);
export default function BoundingBoxVisibility() {

View File

@ -1,9 +1,5 @@
import React, { ChangeEvent } from 'react';
import {
RootState,
useAppDispatch,
useAppSelector,
} from '../../../../app/store';
import { useAppDispatch, useAppSelector } from '../../../../app/store';
import _ from 'lodash';
import { createSelector } from '@reduxjs/toolkit';
import IAISwitch from '../../../../common/components/IAISwitch';

View File

@ -1,5 +1,4 @@
import { Image, useToast } from '@chakra-ui/react';
import { SyntheticEvent } from 'react';
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
import ImageUploaderIconButton from 'common/components/ImageUploaderIconButton';
import { clearInitialImage } from 'features/options/optionsSlice';

View File

@ -1,5 +1,4 @@
import { createSelector } from '@reduxjs/toolkit';
// import IAICanvas from 'features/canvas/IAICanvas';
import IAICanvasControls from 'features/canvas/IAICanvasControls';
import IAICanvasResizer from 'features/canvas/IAICanvasResizer';
import _ from 'lodash';
@ -9,23 +8,25 @@ import ImageUploadButton from 'common/components/ImageUploaderButton';
import CurrentImageDisplay from 'features/gallery/CurrentImageDisplay';
import { OptionsState } from 'features/options/optionsSlice';
import {
baseCanvasImageSelector,
CanvasState,
setDoesCanvasNeedScaling,
} from 'features/canvas/canvasSlice';
import IAICanvas from 'features/canvas/IAICanvas';
const inpaintingDisplaySelector = createSelector(
[(state: RootState) => state.canvas, (state: RootState) => state.options],
(canvas: CanvasState, options: OptionsState) => {
const {
doesCanvasNeedScaling,
inpainting: { imageToInpaint },
} = canvas;
[
baseCanvasImageSelector,
(state: RootState) => state.canvas,
(state: RootState) => state.options,
],
(baseCanvasImage, canvas: CanvasState, options: OptionsState) => {
const { doesCanvasNeedScaling } = canvas;
const { showDualDisplay } = options;
return {
doesCanvasNeedScaling,
showDualDisplay,
imageToInpaint,
baseCanvasImage,
};
},
{
@ -37,7 +38,7 @@ const inpaintingDisplaySelector = createSelector(
const InpaintingDisplay = () => {
const dispatch = useAppDispatch();
const { showDualDisplay, doesCanvasNeedScaling, imageToInpaint } =
const { showDualDisplay, doesCanvasNeedScaling, baseCanvasImage } =
useAppSelector(inpaintingDisplaySelector);
useLayoutEffect(() => {
@ -49,7 +50,7 @@ const InpaintingDisplay = () => {
return () => window.removeEventListener('resize', resizeCallback);
}, [dispatch]);
const inpaintingComponent = imageToInpaint ? (
const inpaintingComponent = baseCanvasImage ? (
<div className="inpainting-main-area">
<IAICanvasControls />
<div className="inpainting-canvas-area">

View File

@ -4,7 +4,6 @@ import React, { ReactElement } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
import NodesWIP from 'common/components/WorkInProgress/NodesWIP';
import OutpaintingWIP from 'common/components/WorkInProgress/OutpaintingWIP';
import { PostProcessingWIP } from 'common/components/WorkInProgress/PostProcessingWIP';
import ImageToImageIcon from 'common/icons/ImageToImageIcon';
import InpaintIcon from 'common/icons/InpaintIcon';
@ -19,13 +18,9 @@ import {
} from 'features/options/optionsSlice';
import ImageToImageWorkarea from './ImageToImage';
import InpaintingWorkarea from './Inpainting/InpaintingWorkarea';
// import { setDoesCanvasNeedScaling } from './Inpainting/inpaintingSlice';
import TextToImageWorkarea from './TextToImage';
import Lightbox from 'features/lightbox/Lightbox';
import {
setCurrentCanvas,
setDoesCanvasNeedScaling,
} from 'features/canvas/canvasSlice';
import { setDoesCanvasNeedScaling } from 'features/canvas/canvasSlice';
import OutpaintingWorkarea from './Outpainting/OutpaintingWorkarea';
import { setShouldShowGallery } from 'features/gallery/gallerySlice';

View File

@ -19,7 +19,6 @@ const workareaSelector = createSelector(
return {
showDualDisplay,
shouldPinOptionsPanel,
activeTabName,
isLightBoxOpen,
shouldShowDualDisplayButton: ['inpainting'].includes(activeTabName),
};
@ -37,7 +36,6 @@ const InvokeWorkarea = (props: InvokeWorkareaProps) => {
const { optionsPanel, children, styleClass } = props;
const {
showDualDisplay,
activeTabName,
isLightBoxOpen,
shouldShowDualDisplayButton,
} = useAppSelector(workareaSelector);

View File

@ -1,34 +1,26 @@
import { createSelector } from '@reduxjs/toolkit';
// import IAICanvas from 'features/canvas/IAICanvas';
import IAICanvasControls from 'features/canvas/IAICanvasControls';
import IAICanvasResizer from 'features/canvas/IAICanvasResizer';
import _ from 'lodash';
import { useLayoutEffect } from 'react';
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
import ImageUploadButton from 'common/components/ImageUploaderButton';
import CurrentImageDisplay from 'features/gallery/CurrentImageDisplay';
import { OptionsState } from 'features/options/optionsSlice';
import {
CanvasState,
currentCanvasSelector,
GenericCanvasState,
OutpaintingCanvasState,
setDoesCanvasNeedScaling,
} from 'features/canvas/canvasSlice';
import IAICanvas from 'features/canvas/IAICanvas';
import IAICanvasOutpaintingControls from 'features/canvas/IAICanvasOutpaintingControls';
const outpaintingDisplaySelector = createSelector(
[(state: RootState) => state.canvas, (state: RootState) => state.options],
(canvas: CanvasState, options: OptionsState) => {
[(state: RootState) => state.canvas],
(canvas: CanvasState) => {
const {
doesCanvasNeedScaling,
outpainting: { objects },
} = canvas;
const { showDualDisplay } = options;
return {
doesCanvasNeedScaling,
showDualDisplay,
doesOutpaintingHaveObjects: objects.length > 0,
};
},
@ -41,8 +33,9 @@ const outpaintingDisplaySelector = createSelector(
const OutpaintingDisplay = () => {
const dispatch = useAppDispatch();
const { showDualDisplay, doesCanvasNeedScaling, doesOutpaintingHaveObjects } =
useAppSelector(outpaintingDisplaySelector);
const { doesCanvasNeedScaling, doesOutpaintingHaveObjects } = useAppSelector(
outpaintingDisplaySelector
);
useLayoutEffect(() => {
const resizeCallback = _.debounce(