From 223e0529ba908d387392c3c6d400b8d437733a1b Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:42:47 +1100 Subject: [PATCH] Fixes app after removing in/out-painting refs --- backend/invoke_ai_web_server.py | 49 ++++------- frontend/src/app/App.tsx | 4 +- .../src/app/selectors/readinessSelector.ts | 5 -- frontend/src/app/socketio/emitters.ts | 34 ++++---- frontend/src/app/socketio/listeners.ts | 31 ++----- frontend/src/app/store.ts | 17 +--- .../src/common/components/ImageUploader.tsx | 2 +- .../src/common/icons/UnifiedCanvas.afdesign | Bin 0 -> 39500 bytes .../src/common/icons/UnifiedCanvasIcon.tsx | 16 ++++ .../icons/design_files/UnifiedCanvas.afdesign | Bin 0 -> 39508 bytes .../icons/design_files/UnifiedCanvas.svg | 7 ++ .../src/common/util/parameterTranslation.ts | 69 +++++++-------- frontend/src/features/canvas/IAICanvas.tsx | 10 +-- .../IAICanvasBrushControl.tsx | 6 +- .../IAICanvasClearImageControl.tsx | 21 ----- .../IAICanvasMaskVisibilityControl.tsx | 2 +- .../features/canvas/IAICanvasEraserLines.tsx | 49 ----------- .../src/features/canvas/IAICanvasResizer.tsx | 32 +------ .../src/features/canvas/canvasReducers.ts | 2 +- frontend/src/features/canvas/canvasSlice.ts | 25 ++---- .../features/canvas/hooks/useCanvasHotkeys.ts | 7 +- .../features/canvas/hooks/useCanvasZoom.ts | 7 +- .../features/gallery/CurrentImageButtons.tsx | 16 ++-- .../src/features/gallery/HoverableImage.tsx | 27 ++++-- .../src/features/gallery/ImageGallery.tsx | 2 +- .../options/MainOptions/MainHeight.tsx | 2 +- .../options/MainOptions/MainWidth.tsx | 2 +- .../system/HotkeysModal/HotkeysModal.tsx | 17 +--- .../tabs/Inpainting/InpaintingDisplay.tsx | 80 ------------------ .../tabs/Inpainting/InpaintingPanel.tsx | 65 -------------- frontend/src/features/tabs/InvokeTabs.tsx | 17 ++-- .../tabs/Outpainting/OutpaintingWorkarea.tsx | 21 ----- .../UnifiedCanvasDisplay.tsx} | 23 ++--- .../UnifiedCanvasPanel.tsx} | 2 +- .../UnifiedCanvasWorkarea.tsx} | 10 +-- 35 files changed, 170 insertions(+), 509 deletions(-) create mode 100644 frontend/src/common/icons/UnifiedCanvas.afdesign create mode 100644 frontend/src/common/icons/UnifiedCanvasIcon.tsx create mode 100644 frontend/src/common/icons/design_files/UnifiedCanvas.afdesign create mode 100644 frontend/src/common/icons/design_files/UnifiedCanvas.svg delete mode 100644 frontend/src/features/canvas/IAICanvasControls/IAICanvasClearImageControl.tsx delete mode 100644 frontend/src/features/canvas/IAICanvasEraserLines.tsx delete mode 100644 frontend/src/features/tabs/Inpainting/InpaintingDisplay.tsx delete mode 100644 frontend/src/features/tabs/Inpainting/InpaintingPanel.tsx delete mode 100644 frontend/src/features/tabs/Outpainting/OutpaintingWorkarea.tsx rename frontend/src/features/tabs/{Outpainting/OutpaintingDisplay.tsx => UnifiedCanvas/UnifiedCanvasDisplay.tsx} (71%) rename frontend/src/features/tabs/{Outpainting/OutpaintingPanel.tsx => UnifiedCanvas/UnifiedCanvasPanel.tsx} (98%) rename frontend/src/features/tabs/{Inpainting/InpaintingWorkarea.tsx => UnifiedCanvas/UnifiedCanvasWorkarea.tsx} (65%) diff --git a/backend/invoke_ai_web_server.py b/backend/invoke_ai_web_server.py index 0a3877edf0..271407381d 100644 --- a/backend/invoke_ai_web_server.py +++ b/backend/invoke_ai_web_server.py @@ -616,10 +616,7 @@ class InvokeAIWebServer: """ Prepare for generation based on generation_mode """ - if generation_parameters["generation_mode"] in [ - "outpainting", - "inpainting", - ]: + if generation_parameters["generation_mode"] == "unifiedCanvas": """ generation_parameters["init_img"] is a base64 image generation_parameters["init_mask"] is a base64 image @@ -634,35 +631,23 @@ class InvokeAIWebServer: original_bounding_box = generation_parameters["bounding_box"].copy() - if generation_parameters["generation_mode"] == "outpainting": - initial_image = dataURL_to_image( - generation_parameters["init_img"] - ).convert("RGBA") + initial_image = dataURL_to_image( + generation_parameters["init_img"] + ).convert("RGBA") - """ - The outpaint image and mask are pre-cropped by the UI, so the bounding box we pass - to the generator should be: - { - "x": 0, - "y": 0, - "width": original_bounding_box["width"], - "height": original_bounding_box["height"] - } - """ + """ + The outpaint image and mask are pre-cropped by the UI, so the bounding box we pass + to the generator should be: + { + "x": 0, + "y": 0, + "width": original_bounding_box["width"], + "height": original_bounding_box["height"] + } + """ - generation_parameters["bounding_box"]["x"] = 0 - generation_parameters["bounding_box"]["y"] = 0 - elif generation_parameters["generation_mode"] == "inpainting": - init_img_path = self.get_image_path_from_url(init_img_url) - initial_image = Image.open(init_img_path) - - """ - For inpainting, only the mask is pre-cropped by the UI, so we need to crop out a copy - of the region of the image to be inpainted to match the size of the mask image. - """ - initial_image = copy_image_from_bounding_box( - initial_image, **generation_parameters["bounding_box"] - ) + generation_parameters["bounding_box"]["x"] = 0 + generation_parameters["bounding_box"]["y"] = 0 # Convert mask dataURL to an image and convert to greyscale mask_image = dataURL_to_image( @@ -930,7 +915,7 @@ class InvokeAIWebServer: if "init_mask" in all_parameters: all_parameters["init_mask"] = "" # TODO: store the mask in metadata - if generation_parameters["generation_mode"] == "outpainting": + if generation_parameters["generation_mode"] == "unifiedCanvas": all_parameters["bounding_box"] = original_bounding_box metadata = self.parameters_to_generated_image_metadata(all_parameters) diff --git a/frontend/src/app/App.tsx b/frontend/src/app/App.tsx index 0e781ed972..c8b0c117a9 100644 --- a/frontend/src/app/App.tsx +++ b/frontend/src/app/App.tsx @@ -50,7 +50,7 @@ const appSelector = createSelector( const shouldShowGalleryButton = !(shouldShowGallery || (shouldHoldGalleryOpen && !shouldPinGallery)) && - ['txt2img', 'img2img', 'inpainting', 'outpainting'].includes( + ['txt2img', 'img2img', 'unifiedCanvas'].includes( activeTabName ); @@ -59,7 +59,7 @@ const appSelector = createSelector( shouldShowOptionsPanel || (shouldHoldOptionsPanelOpen && !shouldPinOptionsPanel) ) && - ['txt2img', 'img2img', 'inpainting', 'outpainting'].includes( + ['txt2img', 'img2img', 'unifiedCanvas'].includes( activeTabName ); diff --git a/frontend/src/app/selectors/readinessSelector.ts b/frontend/src/app/selectors/readinessSelector.ts index 1b3ca83ca8..b8ca488201 100644 --- a/frontend/src/app/selectors/readinessSelector.ts +++ b/frontend/src/app/selectors/readinessSelector.ts @@ -44,11 +44,6 @@ export const readinessSelector = createSelector( reasonsWhyNotReady.push('No initial image selected'); } - if (activeTabName === 'inpainting' && !initialCanvasImage) { - isReady = false; - reasonsWhyNotReady.push('No inpainting image selected'); - } - // TODO: job queue // Cannot generate if already processing an image if (isProcessing) { diff --git a/frontend/src/app/socketio/emitters.ts b/frontend/src/app/socketio/emitters.ts index f72e9697e8..651180d32a 100644 --- a/frontend/src/app/socketio/emitters.ts +++ b/frontend/src/app/socketio/emitters.ts @@ -54,24 +54,26 @@ const makeSocketIOEmitters = ( systemState, }; - if (generationMode === 'inpainting') { - const initialCanvasImage = initialCanvasImageSelector(getState()); - const imageUrl = initialCanvasImage?.image.url; + // if (generationMode === 'inpainting') { + // const initialCanvasImage = initialCanvasImageSelector(getState()); + // const imageUrl = initialCanvasImage?.image.url; - if (!imageUrl) { - dispatch( - addLogEntry({ - timestamp: dateFormat(new Date(), 'isoDateTime'), - message: 'Inpainting image not loaded, cannot generate image.', - level: 'error', - }) - ); - dispatch(errorOccurred()); - return; - } + // if (!imageUrl) { + // dispatch( + // addLogEntry({ + // timestamp: dateFormat(new Date(), 'isoDateTime'), + // message: 'Inpainting image not loaded, cannot generate image.', + // level: 'error', + // }) + // ); + // dispatch(errorOccurred()); + // return; + // } - frontendToBackendParametersConfig.imageToProcessUrl = imageUrl; - } else if (!['txt2img', 'img2img'].includes(generationMode)) { + // frontendToBackendParametersConfig.imageToProcessUrl = imageUrl; + // } else + + if (!['txt2img', 'img2img'].includes(generationMode)) { if (!galleryState.currentImage?.url) return; frontendToBackendParametersConfig.imageToProcessUrl = diff --git a/frontend/src/app/socketio/listeners.ts b/frontend/src/app/socketio/listeners.ts index 842129d267..1c6dc7dd1f 100644 --- a/frontend/src/app/socketio/listeners.ts +++ b/frontend/src/app/socketio/listeners.ts @@ -37,10 +37,7 @@ import { requestNewImages, requestSystemConfig, } from './actions'; -import { - addImageToStagingArea, - setImageToInpaint, -} from 'features/canvas/canvasSlice'; +import { addImageToStagingArea } from 'features/canvas/canvasSlice'; import { tabMap } from 'features/tabs/InvokeTabs'; /** @@ -120,23 +117,15 @@ const makeSocketIOListeners = ( ); } - if ( - ['inpainting', 'outpainting'].includes(generationMode) && - data.boundingBox - ) { + if (generationMode === 'unifiedCanvas' && data.boundingBox) { newImage.category = 'temp'; const { boundingBox } = data; - - if (generationMode === 'inpainting') { - dispatch(setImageToInpaint(newImage)); - } else { - dispatch( - addImageToStagingArea({ - image: newImage, - boundingBox, - }) - ); - } + dispatch( + addImageToStagingArea({ + image: newImage, + boundingBox, + }) + ); } if (shouldLoopback) { @@ -146,10 +135,6 @@ const makeSocketIOListeners = ( dispatch(setInitialImage(newImage)); break; } - case 'inpainting': { - dispatch(setImageToInpaint(newImage)); - break; - } } } diff --git a/frontend/src/app/store.ts b/frontend/src/app/store.ts index 4af37c195b..836f4954f5 100644 --- a/frontend/src/app/store.ts +++ b/frontend/src/app/store.ts @@ -28,14 +28,8 @@ import { socketioMiddleware } from './socketio/middleware'; * The necesssary nested persistors with blacklists are configured below. */ -const genericCanvasBlacklist = ['cursorPosition']; - -const inpaintingCanvasBlacklist = genericCanvasBlacklist.map( - (blacklistItem) => `canvas.inpainting.${blacklistItem}` -); - -const outpaintingCanvasBlacklist = genericCanvasBlacklist.map( - (blacklistItem) => `canvas.outpainting.${blacklistItem}` +const canvasBlacklist = ['cursorPosition'].map( + (blacklistItem) => `canvas.${blacklistItem}` ); const systemBlacklist = [ @@ -73,12 +67,7 @@ const rootPersistConfig = getPersistConfig({ key: 'root', storage, rootReducer, - blacklist: [ - ...inpaintingCanvasBlacklist, - ...outpaintingCanvasBlacklist, - ...systemBlacklist, - ...galleryBlacklist, - ], + blacklist: [...canvasBlacklist, ...systemBlacklist, ...galleryBlacklist], debounce: 300, }); diff --git a/frontend/src/common/components/ImageUploader.tsx b/frontend/src/common/components/ImageUploader.tsx index 6427736df1..a7afda2b96 100644 --- a/frontend/src/common/components/ImageUploader.tsx +++ b/frontend/src/common/components/ImageUploader.tsx @@ -135,7 +135,7 @@ const ImageUploader = (props: ImageUploaderProps) => { }; }, [dispatch, toast, activeTabName]); - const overlaySecondaryText = ['img2img', 'inpainting'].includes(activeTabName) + const overlaySecondaryText = ['img2img', 'unifiedCanvas'].includes(activeTabName) ? ` to ${tabDict[activeTabName as keyof typeof tabDict].tooltip}` : ``; diff --git a/frontend/src/common/icons/UnifiedCanvas.afdesign b/frontend/src/common/icons/UnifiedCanvas.afdesign new file mode 100644 index 0000000000000000000000000000000000000000..d4f7b149ced668855dff9c0a35b5e119ce85080c GIT binary patch literal 39500 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 BI?Mn7 literal 0 HcmV?d00001 diff --git a/frontend/src/common/icons/UnifiedCanvasIcon.tsx b/frontend/src/common/icons/UnifiedCanvasIcon.tsx new file mode 100644 index 0000000000..daa8ecf8a9 --- /dev/null +++ b/frontend/src/common/icons/UnifiedCanvasIcon.tsx @@ -0,0 +1,16 @@ +import { createIcon } from '@chakra-ui/react'; + +const UnifiedCanvasIcon = createIcon({ + displayName: 'UnifiedCanvasIcon', + viewBox: '0 0 3544 3544', + path: ( + + ), +}); + +export default UnifiedCanvasIcon; diff --git a/frontend/src/common/icons/design_files/UnifiedCanvas.afdesign b/frontend/src/common/icons/design_files/UnifiedCanvas.afdesign new file mode 100644 index 0000000000000000000000000000000000000000..4248d3a41d7ff6339e35501d36c1386416936a8e GIT binary patch literal 39508 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 + + + + + + diff --git a/frontend/src/common/util/parameterTranslation.ts b/frontend/src/common/util/parameterTranslation.ts index 88177e3eef..b00157266b 100644 --- a/frontend/src/common/util/parameterTranslation.ts +++ b/frontend/src/common/util/parameterTranslation.ts @@ -106,10 +106,7 @@ export const frontendToBackendParameters = ( } // inpainting exclusive parameters - if ( - ['inpainting', 'outpainting'].includes(generationMode) && - canvasImageLayerRef.current - ) { + if (generationMode === 'unifiedCanvas' && canvasImageLayerRef.current) { const { layerState: { objects }, boundingBoxCoordinates, @@ -146,44 +143,42 @@ export const frontendToBackendParameters = ( generationParameters.bounding_box = boundingBox; - if (generationMode === 'outpainting') { - const tempScale = canvasImageLayerRef.current.scale(); + const tempScale = canvasImageLayerRef.current.scale(); - canvasImageLayerRef.current.scale({ - x: 1 / stageScale, - y: 1 / stageScale, - }); + canvasImageLayerRef.current.scale({ + x: 1 / stageScale, + y: 1 / stageScale, + }); - const absPos = canvasImageLayerRef.current.getAbsolutePosition(); + const absPos = canvasImageLayerRef.current.getAbsolutePosition(); - const imageDataURL = canvasImageLayerRef.current.toDataURL({ - x: boundingBox.x + absPos.x, - y: boundingBox.y + absPos.y, - width: boundingBox.width, - height: boundingBox.height, - }); + const imageDataURL = canvasImageLayerRef.current.toDataURL({ + x: boundingBox.x + absPos.x, + y: boundingBox.y + absPos.y, + width: boundingBox.width, + height: boundingBox.height, + }); - if (enableImageDebugging) { - openBase64ImageInTab([ - { base64: maskDataURL, caption: 'mask sent as init_mask' }, - { base64: imageDataURL, caption: 'image sent as init_img' }, - ]); - } - - canvasImageLayerRef.current.scale(tempScale); - - generationParameters.init_img = imageDataURL; - - // TODO: The server metadata generation needs to be changed to fix this. - generationParameters.progress_images = false; - - generationParameters.seam_size = 96; - generationParameters.seam_blur = 16; - generationParameters.seam_strength = 0.7; - generationParameters.seam_steps = 10; - generationParameters.tile_size = 32; - generationParameters.force_outpaint = false; + if (enableImageDebugging) { + openBase64ImageInTab([ + { base64: maskDataURL, caption: 'mask sent as init_mask' }, + { base64: imageDataURL, caption: 'image sent as init_img' }, + ]); } + + canvasImageLayerRef.current.scale(tempScale); + + generationParameters.init_img = imageDataURL; + + // TODO: The server metadata generation needs to be changed to fix this. + generationParameters.progress_images = false; + + generationParameters.seam_size = 96; + generationParameters.seam_blur = 16; + generationParameters.seam_strength = 0.7; + generationParameters.seam_steps = 10; + generationParameters.tile_size = 32; + generationParameters.force_outpaint = false; } if (shouldGenerateVariations) { diff --git a/frontend/src/features/canvas/IAICanvas.tsx b/frontend/src/features/canvas/IAICanvas.tsx index 2fd89162b6..1620b132ac 100644 --- a/frontend/src/features/canvas/IAICanvas.tsx +++ b/frontend/src/features/canvas/IAICanvas.tsx @@ -93,7 +93,6 @@ const selector = createSelector( stageDimensions, stageScale, tool, - isOnOutpaintingTab: activeTabName === 'outpainting', isStaging, shouldShowIntermediates, shouldLockToInitialImage, @@ -122,7 +121,6 @@ const IAICanvas = () => { stageDimensions, stageScale, tool, - isOnOutpaintingTab, isStaging, shouldShowIntermediates, shouldLockToInitialImage, @@ -207,11 +205,7 @@ const IAICanvas = () => { onDragEnd={handleDragEnd} onWheel={handleWheel} listening={(tool === 'move' || isStaging) && !isModifyingBoundingBox} - draggable={ - (tool === 'move' || isStaging) && - !isModifyingBoundingBox && - isOnOutpaintingTab - } + draggable={(tool === 'move' || isStaging) && !isModifyingBoundingBox} > @@ -243,7 +237,7 @@ const IAICanvas = () => { /> - {isOnOutpaintingTab && } + diff --git a/frontend/src/features/canvas/IAICanvasControls/IAICanvasBrushControl.tsx b/frontend/src/features/canvas/IAICanvasControls/IAICanvasBrushControl.tsx index dbd2609d6e..d0e0d736ae 100644 --- a/frontend/src/features/canvas/IAICanvasControls/IAICanvasBrushControl.tsx +++ b/frontend/src/features/canvas/IAICanvasControls/IAICanvasBrushControl.tsx @@ -18,7 +18,7 @@ import { import _ from 'lodash'; import IAICanvasMaskColorPicker from './IAICanvasMaskControls/IAICanvasMaskColorPicker'; -const inpaintingBrushSelector = createSelector( +const selector = createSelector( [canvasSelector, activeTabNameSelector], (canvas, activeTabName) => { const { tool, brushSize } = canvas; @@ -38,9 +38,7 @@ const inpaintingBrushSelector = createSelector( export default function IAICanvasBrushControl() { const dispatch = useAppDispatch(); - const { tool, brushSize, activeTabName } = useAppSelector( - inpaintingBrushSelector - ); + const { tool, brushSize, activeTabName } = useAppSelector(selector); const handleSelectBrushTool = () => dispatch(setTool('brush')); diff --git a/frontend/src/features/canvas/IAICanvasControls/IAICanvasClearImageControl.tsx b/frontend/src/features/canvas/IAICanvasControls/IAICanvasClearImageControl.tsx deleted file mode 100644 index af04cc35f7..0000000000 --- a/frontend/src/features/canvas/IAICanvasControls/IAICanvasClearImageControl.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { FaTrash } from 'react-icons/fa'; -import { useAppDispatch } from 'app/store'; -import IAIIconButton from 'common/components/IAIIconButton'; -import { clearImageToInpaint } from 'features/canvas/canvasSlice'; - -export default function IAICanvasClearImageControl() { - const dispatch = useAppDispatch(); - - const handleClearImage = () => { - dispatch(clearImageToInpaint()); - }; - - return ( - } - onClick={handleClearImage} - /> - ); -} diff --git a/frontend/src/features/canvas/IAICanvasControls/IAICanvasMaskControls/IAICanvasMaskVisibilityControl.tsx b/frontend/src/features/canvas/IAICanvasControls/IAICanvasMaskControls/IAICanvasMaskVisibilityControl.tsx index 5bc2c36201..f54b8bf08f 100644 --- a/frontend/src/features/canvas/IAICanvasControls/IAICanvasMaskControls/IAICanvasMaskVisibilityControl.tsx +++ b/frontend/src/features/canvas/IAICanvasControls/IAICanvasMaskControls/IAICanvasMaskVisibilityControl.tsx @@ -40,7 +40,7 @@ export default function IAICanvasMaskVisibilityControl() { handleToggleShouldShowMask(); }, { - enabled: activeTabName === 'inpainting' || activeTabName == 'outpainting', + enabled: activeTabName === 'unifiedCanvas', }, [activeTabName, isMaskEnabled] ); diff --git a/frontend/src/features/canvas/IAICanvasEraserLines.tsx b/frontend/src/features/canvas/IAICanvasEraserLines.tsx deleted file mode 100644 index 9513ac0fef..0000000000 --- a/frontend/src/features/canvas/IAICanvasEraserLines.tsx +++ /dev/null @@ -1,49 +0,0 @@ -// import { GroupConfig } from 'konva/lib/Group'; -// import { Group, Line } from 'react-konva'; -// import { RootState, useAppSelector } from 'app/store'; -// import { createSelector } from '@reduxjs/toolkit'; -// import { OutpaintingCanvasState } from './canvasSlice'; - -// export const canvasEraserLinesSelector = createSelector( -// (state: RootState) => state.canvas.outpainting, -// (outpainting: OutpaintingCanvasState) => { -// const { eraserLines } = outpainting; -// return { -// eraserLines, -// }; -// } -// ); - -// type IAICanvasEraserLinesProps = GroupConfig; - -// /** -// * Draws the lines which comprise the mask. -// * -// * Uses globalCompositeOperation to handle the brush and eraser tools. -// */ -// const IAICanvasEraserLines = (props: IAICanvasEraserLinesProps) => { -// const { ...rest } = props; -// const { eraserLines } = useAppSelector(canvasEraserLinesSelector); - -// return ( -// -// {eraserLines.map((line, i) => ( -// 0 -// strokeWidth={line.strokeWidth * 2} -// tension={0} -// lineCap="round" -// lineJoin="round" -// shadowForStrokeEnabled={false} -// listening={false} -// globalCompositeOperation={'source-over'} -// /> -// ))} -// -// ); -// }; - -// export default IAICanvasEraserLines; -export default {} \ No newline at end of file diff --git a/frontend/src/features/canvas/IAICanvasResizer.tsx b/frontend/src/features/canvas/IAICanvasResizer.tsx index 483bc47abc..28bc02c5b1 100644 --- a/frontend/src/features/canvas/IAICanvasResizer.tsx +++ b/frontend/src/features/canvas/IAICanvasResizer.tsx @@ -52,9 +52,6 @@ const IAICanvasResizer = () => { if (!initialCanvasImage?.image) return; - const { width: imageWidth, height: imageHeight } = - initialCanvasImage.image; - dispatch( setCanvasContainerDimensions({ width: clientWidth, @@ -69,34 +66,6 @@ const IAICanvasResizer = () => { } dispatch(setDoesCanvasNeedScaling(false)); - // } - // if ((activeTabName === 'inpainting') && initialCanvasImage?.image) { - // const { width: imageWidth, height: imageHeight } = - // initialCanvasImage.image; - - // const scale = Math.min( - // 1, - // Math.min(clientWidth / imageWidth, clientHeight / imageHeight) - // ); - - // dispatch(setStageScale(scale)); - - // dispatch( - // setStageDimensions({ - // width: Math.floor(imageWidth * scale), - // height: Math.floor(imageHeight * scale), - // }) - // ); - // dispatch(setDoesCanvasNeedScaling(false)); - // } else if (activeTabName === 'outpainting') { - // dispatch( - // setStageDimensions({ - // width: Math.floor(clientWidth), - // height: Math.floor(clientHeight), - // }) - // ); - // dispatch(setDoesCanvasNeedScaling(false)); - // } }, 0); }, [ dispatch, @@ -104,6 +73,7 @@ const IAICanvasResizer = () => { doesCanvasNeedScaling, activeTabName, isCanvasInitialized, + shouldLockToInitialImage, ]); return ( diff --git a/frontend/src/features/canvas/canvasReducers.ts b/frontend/src/features/canvas/canvasReducers.ts index e70bfddb55..bff50eebc4 100644 --- a/frontend/src/features/canvas/canvasReducers.ts +++ b/frontend/src/features/canvas/canvasReducers.ts @@ -6,7 +6,7 @@ import { } from 'common/util/roundDownToMultiple'; import _ from 'lodash'; -export const setInitialCanvasImage = ( +export const setInitialCanvasImage_reducer = ( state: CanvasState, image: InvokeAI.Image ) => { diff --git a/frontend/src/features/canvas/canvasSlice.ts b/frontend/src/features/canvas/canvasSlice.ts index 13f8f5ae14..8e86b7c8c2 100644 --- a/frontend/src/features/canvas/canvasSlice.ts +++ b/frontend/src/features/canvas/canvasSlice.ts @@ -8,13 +8,11 @@ import { roundDownToMultiple } from 'common/util/roundDownToMultiple'; import { RootState } from 'app/store'; import { mergeAndUploadCanvas } from './util/mergeAndUploadCanvas'; import { uploadImage } from 'features/gallery/util/uploadImage'; -import { setInitialCanvasImage } from './canvasReducers'; +import { setInitialCanvasImage_reducer } from './canvasReducers'; import calculateScale from './util/calculateScale'; import calculateCoordinates from './util/calculateCoordinates'; import floorCoordinates from './util/floorCoordinates'; -export type CanvasMode = 'inpainting' | 'outpainting'; - export type CanvasLayer = 'base' | 'mask'; export type CanvasDrawingTool = 'brush' | 'eraser'; @@ -256,15 +254,8 @@ export const canvasSlice = createSlice({ setCursorPosition: (state, action: PayloadAction) => { state.cursorPosition = action.payload; }, - clearImageToInpaint: (state) => { - // TODO - // state.inpainting.imageToInpaint = undefined; - }, - setImageToOutpaint: (state, action: PayloadAction) => { - setInitialCanvasImage(state, action.payload); - }, - setImageToInpaint: (state, action: PayloadAction) => { - setInitialCanvasImage(state, action.payload); + setInitialCanvasImage: (state, action: PayloadAction) => { + setInitialCanvasImage_reducer(state, action.payload); }, setStageDimensions: (state, action: PayloadAction) => { state.stageDimensions = action.payload; @@ -642,10 +633,8 @@ export const canvasSlice = createSlice({ if (kind !== 'init') return; - if (activeTabName === 'inpainting') { - setInitialCanvasImage(state, image); - } else if (activeTabName === 'outpainting') { - setInitialCanvasImage(state, image); + if (activeTabName === 'unifiedCanvas') { + setInitialCanvasImage_reducer(state, image); } }); }, @@ -665,13 +654,11 @@ export const { setShouldShowBrushPreview, setMaskColor, clearMask, - clearImageToInpaint, undo, redo, setCursorPosition, setStageDimensions, - setImageToInpaint, - setImageToOutpaint, + setInitialCanvasImage, setBoundingBoxDimensions, setBoundingBoxCoordinates, setBoundingBoxPreviewFill, diff --git a/frontend/src/features/canvas/hooks/useCanvasHotkeys.ts b/frontend/src/features/canvas/hooks/useCanvasHotkeys.ts index dcb7265b85..870c8b0ffb 100644 --- a/frontend/src/features/canvas/hooks/useCanvasHotkeys.ts +++ b/frontend/src/features/canvas/hooks/useCanvasHotkeys.ts @@ -13,7 +13,7 @@ import { canvasSelector } from '../canvasSlice'; import { useRef } from 'react'; import { stageRef } from '../IAICanvas'; -const inpaintingCanvasHotkeysSelector = createSelector( +const selector = createSelector( [canvasSelector, activeTabNameSelector], (canvas, activeTabName) => { const { @@ -40,9 +40,8 @@ const inpaintingCanvasHotkeysSelector = createSelector( const useInpaintingCanvasHotkeys = () => { const dispatch = useAppDispatch(); - const { activeTabName, shouldShowBoundingBox, tool } = useAppSelector( - inpaintingCanvasHotkeysSelector - ); + const { activeTabName, shouldShowBoundingBox, tool } = + useAppSelector(selector); const previousToolRef = useRef(null); // Toggle lock bounding box diff --git a/frontend/src/features/canvas/hooks/useCanvasZoom.ts b/frontend/src/features/canvas/hooks/useCanvasZoom.ts index 1674b6663c..7f8ac5a50c 100644 --- a/frontend/src/features/canvas/hooks/useCanvasZoom.ts +++ b/frontend/src/features/canvas/hooks/useCanvasZoom.ts @@ -60,12 +60,7 @@ const useCanvasWheel = (stageRef: MutableRefObject) => { return useCallback( (e: KonvaEventObject) => { // stop default scrolling - if ( - activeTabName !== 'outpainting' || - !stageRef.current || - isMoveStageKeyHeld || - !initialCanvasImage - ) + if (!stageRef.current || isMoveStageKeyHeld || !initialCanvasImage) return; e.evt.preventDefault(); diff --git a/frontend/src/features/gallery/CurrentImageButtons.tsx b/frontend/src/features/gallery/CurrentImageButtons.tsx index 426c8674c1..c84f7252c0 100644 --- a/frontend/src/features/gallery/CurrentImageButtons.tsx +++ b/frontend/src/features/gallery/CurrentImageButtons.tsx @@ -36,9 +36,9 @@ import { FaTrash, } from 'react-icons/fa'; import { - setImageToInpaint, setDoesCanvasNeedScaling, - setImageToOutpaint, + setInitialCanvasImage, + setShouldLockToInitialImage, } from 'features/canvas/canvasSlice'; import { GalleryState } from './gallerySlice'; import { activeTabNameSelector } from 'features/options/optionsSelectors'; @@ -320,12 +320,12 @@ const CurrentImageButtons = () => { if (!currentImage) return; if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false)); - dispatch(setImageToInpaint(currentImage)); - dispatch(setActiveTab('inpainting')); + dispatch(setInitialCanvasImage(currentImage)); + dispatch(setShouldLockToInitialImage(true)); dispatch(setDoesCanvasNeedScaling(true)); toast({ - title: 'Sent to Inpainting', + title: 'Sent to Unified Canvas', status: 'success', duration: 2500, isClosable: true, @@ -336,12 +336,12 @@ const CurrentImageButtons = () => { if (!currentImage) return; if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false)); - dispatch(setImageToOutpaint(currentImage)); - dispatch(setActiveTab('outpainting')); + dispatch(setInitialCanvasImage(currentImage)); + dispatch(setShouldLockToInitialImage(false)); dispatch(setDoesCanvasNeedScaling(true)); toast({ - title: 'Sent to Inpainting', + title: 'Sent to Unified Canvas', status: 'success', duration: 2500, isClosable: true, diff --git a/frontend/src/features/gallery/HoverableImage.tsx b/frontend/src/features/gallery/HoverableImage.tsx index d7896ce367..11763fb85f 100644 --- a/frontend/src/features/gallery/HoverableImage.tsx +++ b/frontend/src/features/gallery/HoverableImage.tsx @@ -23,8 +23,9 @@ import { import * as InvokeAI from 'app/invokeai'; import * as ContextMenu from '@radix-ui/react-context-menu'; import { - setImageToInpaint, - setImageToOutpaint, + setDoesCanvasNeedScaling, + setInitialCanvasImage, + setShouldLockToInitialImage, } from 'features/canvas/canvasSlice'; import { hoverableImageSelector } from './gallerySliceSelectors'; @@ -97,10 +98,15 @@ const HoverableImage = memo((props: HoverableImageProps) => { const handleSendToInpainting = () => { if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false)); - dispatch(setImageToInpaint(image)); - if (activeTabName !== 'inpainting') { - dispatch(setActiveTab('inpainting')); + + dispatch(setInitialCanvasImage(image)); + dispatch(setShouldLockToInitialImage(true)); + dispatch(setDoesCanvasNeedScaling(true)); + + if (activeTabName !== 'unifiedCanvas') { + dispatch(setActiveTab('unifiedCanvas')); } + toast({ title: 'Sent to Inpainting', status: 'success', @@ -111,10 +117,15 @@ const HoverableImage = memo((props: HoverableImageProps) => { const handleSendToOutpainting = () => { if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false)); - dispatch(setImageToOutpaint(image)); - if (activeTabName !== 'outpainting') { - dispatch(setActiveTab('outpainting')); + + dispatch(setInitialCanvasImage(image)); + dispatch(setShouldLockToInitialImage(true)); + dispatch(setDoesCanvasNeedScaling(true)); + + if (activeTabName !== 'unifiedCanvas') { + dispatch(setActiveTab('unifiedCanvas')); } + toast({ title: 'Sent to Outpainting', status: 'success', diff --git a/frontend/src/features/gallery/ImageGallery.tsx b/frontend/src/features/gallery/ImageGallery.tsx index 321f62325d..41c549132d 100644 --- a/frontend/src/features/gallery/ImageGallery.tsx +++ b/frontend/src/features/gallery/ImageGallery.tsx @@ -76,7 +76,7 @@ export default function ImageGallery() { return; } - if (activeTabName === 'inpainting' || activeTabName === 'outpainting') { + if (activeTabName === 'unifiedCanvas') { dispatch(setGalleryWidth(190)); setGalleryMinWidth(190); setGalleryMaxWidth(190); diff --git a/frontend/src/features/options/MainOptions/MainHeight.tsx b/frontend/src/features/options/MainOptions/MainHeight.tsx index 61ba0eb25c..c5dc0d28ac 100644 --- a/frontend/src/features/options/MainOptions/MainHeight.tsx +++ b/frontend/src/features/options/MainOptions/MainHeight.tsx @@ -15,7 +15,7 @@ export default function MainHeight() { return ( - {renderHotkeyModalItems(inpaintingHotkeys)} - - - - - -

Outpainting Hotkeys

- -
- - {renderHotkeyModalItems(outpaintingHotkeys)} + {renderHotkeyModalItems(unifiedCanvasHotkeys)}
diff --git a/frontend/src/features/tabs/Inpainting/InpaintingDisplay.tsx b/frontend/src/features/tabs/Inpainting/InpaintingDisplay.tsx deleted file mode 100644 index 0e8afb8888..0000000000 --- a/frontend/src/features/tabs/Inpainting/InpaintingDisplay.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -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 { - initialCanvasImageSelector, - CanvasState, - setDoesCanvasNeedScaling, -} from 'features/canvas/canvasSlice'; -import IAICanvas from 'features/canvas/IAICanvas'; - -const inpaintingDisplaySelector = createSelector( - [ - initialCanvasImageSelector, - (state: RootState) => state.canvas, - (state: RootState) => state.options, - ], - (initialCanvasImage, canvas: CanvasState, options: OptionsState) => { - const { doesCanvasNeedScaling } = canvas; - const { showDualDisplay } = options; - return { - doesCanvasNeedScaling, - showDualDisplay, - initialCanvasImage, - }; - }, - { - memoizeOptions: { - resultEqualityCheck: _.isEqual, - }, - } -); - -const InpaintingDisplay = () => { - const dispatch = useAppDispatch(); - const { showDualDisplay, doesCanvasNeedScaling, initialCanvasImage } = - useAppSelector(inpaintingDisplaySelector); - - useLayoutEffect(() => { - const resizeCallback = _.debounce( - () => dispatch(setDoesCanvasNeedScaling(true)), - 250 - ); - window.addEventListener('resize', resizeCallback); - return () => window.removeEventListener('resize', resizeCallback); - }, [dispatch]); - - const inpaintingComponent = initialCanvasImage ? ( -
- -
- {doesCanvasNeedScaling ? : } -
-
- ) : ( - - ); - - return ( -
-
{inpaintingComponent}
- {showDualDisplay && ( -
- -
- )} -
- ); -}; - -export default InpaintingDisplay; diff --git a/frontend/src/features/tabs/Inpainting/InpaintingPanel.tsx b/frontend/src/features/tabs/Inpainting/InpaintingPanel.tsx deleted file mode 100644 index fc2500428e..0000000000 --- a/frontend/src/features/tabs/Inpainting/InpaintingPanel.tsx +++ /dev/null @@ -1,65 +0,0 @@ -// import { Feature } from 'app/features'; -import { Feature } from 'app/features'; -import { RootState, useAppSelector } from 'app/store'; -import FaceRestoreHeader from 'features/options/AdvancedOptions/FaceRestore/FaceRestoreHeader'; -import FaceRestoreOptions from 'features/options/AdvancedOptions/FaceRestore/FaceRestoreOptions'; -import ImageToImageStrength from 'features/options/AdvancedOptions/ImageToImage/ImageToImageStrength'; -import InpaintingSettings from 'features/options/AdvancedOptions/Inpainting/InpaintingSettings'; -import SeedHeader from 'features/options/AdvancedOptions/Seed/SeedHeader'; -import SeedOptions from 'features/options/AdvancedOptions/Seed/SeedOptions'; -import UpscaleHeader from 'features/options/AdvancedOptions/Upscale/UpscaleHeader'; -import UpscaleOptions from 'features/options/AdvancedOptions/Upscale/UpscaleOptions'; -import VariationsHeader from 'features/options/AdvancedOptions/Variations/VariationsHeader'; -import VariationsOptions from 'features/options/AdvancedOptions/Variations/VariationsOptions'; -import MainAdvancedOptionsCheckbox from 'features/options/MainOptions/MainAdvancedOptionsCheckbox'; -import MainOptions from 'features/options/MainOptions/MainOptions'; -import OptionsAccordion from 'features/options/OptionsAccordion'; -import ProcessButtons from 'features/options/ProcessButtons/ProcessButtons'; -import PromptInput from 'features/options/PromptInput/PromptInput'; -import InvokeOptionsPanel from 'features/tabs/InvokeOptionsPanel'; - -export default function InpaintingPanel() { - const showAdvancedOptions = useAppSelector( - (state: RootState) => state.options.showAdvancedOptions - ); - - const imageToImageAccordions = { - seed: { - header: , - feature: Feature.SEED, - options: , - }, - variations: { - header: , - feature: Feature.VARIATIONS, - options: , - }, - face_restore: { - header: , - feature: Feature.FACE_CORRECTION, - options: , - }, - upscale: { - header: , - feature: Feature.UPSCALE, - options: , - }, - }; - - return ( - - - - - - - - {showAdvancedOptions && ( - - )} - - ); -} diff --git a/frontend/src/features/tabs/InvokeTabs.tsx b/frontend/src/features/tabs/InvokeTabs.tsx index 518a542958..6b17c007e8 100644 --- a/frontend/src/features/tabs/InvokeTabs.tsx +++ b/frontend/src/features/tabs/InvokeTabs.tsx @@ -17,12 +17,12 @@ import { setShouldShowOptionsPanel, } from 'features/options/optionsSlice'; import ImageToImageWorkarea from './ImageToImage'; -import InpaintingWorkarea from './Inpainting/InpaintingWorkarea'; import TextToImageWorkarea from './TextToImage'; import Lightbox from 'features/lightbox/Lightbox'; import { setDoesCanvasNeedScaling } from 'features/canvas/canvasSlice'; -import OutpaintingWorkarea from './Outpainting/OutpaintingWorkarea'; +import UnifiedCanvasWorkarea from './UnifiedCanvas/UnifiedCanvasWorkarea'; import { setShouldShowGallery } from 'features/gallery/gallerySlice'; +import UnifiedCanvasIcon from 'common/icons/UnifiedCanvasIcon'; export const tabDict = { txt2img: { @@ -35,15 +35,10 @@ export const tabDict = { workarea: , tooltip: 'Image To Image', }, - inpainting: { - title: , - workarea: , - tooltip: 'Inpainting', - }, - outpainting: { - title: , - workarea: , - tooltip: 'Outpainting', + unifiedCanvas: { + title: , + workarea: , + tooltip: 'Unified Canvas', }, nodes: { title: , diff --git a/frontend/src/features/tabs/Outpainting/OutpaintingWorkarea.tsx b/frontend/src/features/tabs/Outpainting/OutpaintingWorkarea.tsx deleted file mode 100644 index 02d689de52..0000000000 --- a/frontend/src/features/tabs/Outpainting/OutpaintingWorkarea.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import OutpaintingPanel from './OutpaintingPanel'; -import OutpaintingDisplay from './OutpaintingDisplay'; -import InvokeWorkarea from 'features/tabs/InvokeWorkarea'; -import { useAppDispatch } from 'app/store'; -import { useEffect } from 'react'; -import { setDoesCanvasNeedScaling } from 'features/canvas/canvasSlice'; - -export default function OutpaintingWorkarea() { - const dispatch = useAppDispatch(); - useEffect(() => { - dispatch(setDoesCanvasNeedScaling(true)); - }, [dispatch]); - return ( - } - styleClass="inpainting-workarea-overrides" - > - - - ); -} diff --git a/frontend/src/features/tabs/Outpainting/OutpaintingDisplay.tsx b/frontend/src/features/tabs/UnifiedCanvas/UnifiedCanvasDisplay.tsx similarity index 71% rename from frontend/src/features/tabs/Outpainting/OutpaintingDisplay.tsx rename to frontend/src/features/tabs/UnifiedCanvas/UnifiedCanvasDisplay.tsx index 186abe0328..ad8cb8634b 100644 --- a/frontend/src/features/tabs/Outpainting/OutpaintingDisplay.tsx +++ b/frontend/src/features/tabs/UnifiedCanvas/UnifiedCanvasDisplay.tsx @@ -12,7 +12,7 @@ import { import IAICanvas from 'features/canvas/IAICanvas'; import IAICanvasOutpaintingControls from 'features/canvas/IAICanvasOutpaintingControls'; -const outpaintingDisplaySelector = createSelector( +const selector = createSelector( [canvasSelector], (canvas) => { const { @@ -31,11 +31,10 @@ const outpaintingDisplaySelector = createSelector( } ); -const OutpaintingDisplay = () => { +const UnifiedCanvasDisplay = () => { const dispatch = useAppDispatch(); - const { doesCanvasNeedScaling, doesOutpaintingHaveObjects } = useAppSelector( - outpaintingDisplaySelector - ); + const { doesCanvasNeedScaling, doesOutpaintingHaveObjects } = + useAppSelector(selector); useLayoutEffect(() => { const resizeCallback = _.debounce( @@ -46,17 +45,6 @@ const OutpaintingDisplay = () => { return () => window.removeEventListener('resize', resizeCallback); }, [dispatch]); - const outpaintingComponent = doesOutpaintingHaveObjects ? ( -
- -
- {doesCanvasNeedScaling ? : } -
-
- ) : ( - - ); - return (
@@ -67,9 +55,8 @@ const OutpaintingDisplay = () => {
- {/*
{outpaintingComponent}
*/} ); }; -export default OutpaintingDisplay; +export default UnifiedCanvasDisplay; diff --git a/frontend/src/features/tabs/Outpainting/OutpaintingPanel.tsx b/frontend/src/features/tabs/UnifiedCanvas/UnifiedCanvasPanel.tsx similarity index 98% rename from frontend/src/features/tabs/Outpainting/OutpaintingPanel.tsx rename to frontend/src/features/tabs/UnifiedCanvas/UnifiedCanvasPanel.tsx index 5428a923f2..d5ca42137f 100644 --- a/frontend/src/features/tabs/Outpainting/OutpaintingPanel.tsx +++ b/frontend/src/features/tabs/UnifiedCanvas/UnifiedCanvasPanel.tsx @@ -18,7 +18,7 @@ import ProcessButtons from 'features/options/ProcessButtons/ProcessButtons'; import PromptInput from 'features/options/PromptInput/PromptInput'; import InvokeOptionsPanel from 'features/tabs/InvokeOptionsPanel'; -export default function OutpaintingPanel() { +export default function UnifiedCanvasPanel() { const showAdvancedOptions = useAppSelector( (state: RootState) => state.options.showAdvancedOptions ); diff --git a/frontend/src/features/tabs/Inpainting/InpaintingWorkarea.tsx b/frontend/src/features/tabs/UnifiedCanvas/UnifiedCanvasWorkarea.tsx similarity index 65% rename from frontend/src/features/tabs/Inpainting/InpaintingWorkarea.tsx rename to frontend/src/features/tabs/UnifiedCanvas/UnifiedCanvasWorkarea.tsx index cb9dba07d5..0e03a3b118 100644 --- a/frontend/src/features/tabs/Inpainting/InpaintingWorkarea.tsx +++ b/frontend/src/features/tabs/UnifiedCanvas/UnifiedCanvasWorkarea.tsx @@ -1,21 +1,21 @@ -import InpaintingPanel from './InpaintingPanel'; -import InpaintingDisplay from './InpaintingDisplay'; +import UnifiedCanvasPanel from './UnifiedCanvasPanel'; +import UnifiedCanvasDisplay from './UnifiedCanvasDisplay'; import InvokeWorkarea from 'features/tabs/InvokeWorkarea'; import { useAppDispatch } from 'app/store'; import { useEffect } from 'react'; import { setDoesCanvasNeedScaling } from 'features/canvas/canvasSlice'; -export default function InpaintingWorkarea() { +export default function UnifiedCanvasWorkarea() { const dispatch = useAppDispatch(); useEffect(() => { dispatch(setDoesCanvasNeedScaling(true)); }, [dispatch]); return ( } + optionsPanel={} styleClass="inpainting-workarea-overrides" > - + ); }