From 78b456218449dfb4a60e1e4ad76983226d988200 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 8 Jul 2024 23:56:21 +1000 Subject: [PATCH] UNDO ME WIP --- .../listeners/enqueueRequestedLinear.ts | 2 +- .../components/CanvasResizer.tsx | 147 ++++++++++++++++++ .../components/ControlLayersEditor.tsx | 3 + .../components/ControlLayersToolbar.tsx | 2 + .../components/NewSessionButton.tsx | 16 ++ .../controlLayers/konva/CanvasBbox.ts | 8 + .../controlLayers/konva/CanvasManager.ts | 3 +- .../controlLayers/konva/CanvasStagingArea.ts | 2 +- .../controlLayers/konva/CanvasStateApi.ts | 2 +- .../src/features/controlLayers/konva/util.ts | 2 +- .../components/DocumentSize/DocumentSize.tsx | 6 +- 11 files changed, 185 insertions(+), 8 deletions(-) create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CanvasResizer.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/NewSessionButton.tsx diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/enqueueRequestedLinear.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/enqueueRequestedLinear.ts index df29d7cb9c..74425a4600 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/enqueueRequestedLinear.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/enqueueRequestedLinear.ts @@ -18,7 +18,7 @@ export const addEnqueueRequestedLinear = (startAppListening: AppStartListening) const { prepend } = action.payload; let didStartStaging = false; - if (!state.canvasV2.session.isStaging) { + if (!state.canvasV2.session.isStaging && state.canvasV2.session.isActive) { dispatch(sessionStartedStaging()); didStartStaging = true; } diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasResizer.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasResizer.tsx new file mode 100644 index 0000000000..d5fc3852d2 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasResizer.tsx @@ -0,0 +1,147 @@ +import { Flex, Grid, GridItem, IconButton } from '@invoke-ai/ui-library'; +import { useAppSelector } from 'app/store/storeHooks'; +import { memo, useCallback, useState } from 'react'; +import { + PiArrowDownBold, + PiArrowDownLeftBold, + PiArrowDownRightBold, + PiArrowLeftBold, + PiArrowRightBold, + PiArrowUpBold, + PiArrowUpLeftBold, + PiArrowUpRightBold, + PiSquareBold, +} from 'react-icons/pi'; + +type ResizeDirection = + | 'up-left' + | 'up' + | 'up-right' + | 'left' + | 'center-out' + | 'right' + | 'down-left' + | 'down' + | 'down-right'; + +export const CanvasResizer = memo(() => { + const document = useAppSelector((s) => s.canvasV2.document); + const [resizeDirection, setResizeDirection] = useState('center-out'); + + const setDirUpLeft = useCallback(() => { + setResizeDirection('up-left'); + }, []); + + const setDirUp = useCallback(() => { + setResizeDirection('up'); + }, []); + + const setDirUpRight = useCallback(() => { + setResizeDirection('up-right'); + }, []); + + const setDirLeft = useCallback(() => { + setResizeDirection('left'); + }, []); + + const setDirCenterOut = useCallback(() => { + setResizeDirection('center-out'); + }, []); + + const setDirRight = useCallback(() => { + setResizeDirection('right'); + }, []); + + const setDirDownLeft = useCallback(() => { + setResizeDirection('down-left'); + }, []); + + const setDirDown = useCallback(() => { + setResizeDirection('down'); + }, []); + + const setDirDownRight = useCallback(() => { + setResizeDirection('down-right'); + }, []); + + return ( + + + + } + variant={resizeDirection === 'up-left' ? 'solid' : 'ghost'} + /> + + + } + variant={resizeDirection === 'up' ? 'solid' : 'ghost'} + /> + + + } + variant={resizeDirection === 'up-right' ? 'solid' : 'ghost'} + /> + + + } + variant={resizeDirection === 'left' ? 'solid' : 'ghost'} + /> + + + } + variant={resizeDirection === 'center-out' ? 'solid' : 'ghost'} + /> + + + } + variant={resizeDirection === 'right' ? 'solid' : 'ghost'} + /> + + + } + variant={resizeDirection === 'down-left' ? 'solid' : 'ghost'} + /> + + + } + variant={resizeDirection === 'down' ? 'solid' : 'ghost'} + /> + + + } + variant={resizeDirection === 'down-right' ? 'solid' : 'ghost'} + /> + + + + ); +}); + +CanvasResizer.displayName = 'CanvasResizer'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.tsx index 1a3b0c20f9..a2a4bf9126 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.tsx @@ -21,6 +21,9 @@ export const ControlLayersEditor = memo(() => { + {/* + + */} ); }); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersToolbar.tsx b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersToolbar.tsx index 8554c63b2b..e3cc5cb5fa 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersToolbar.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersToolbar.tsx @@ -5,6 +5,7 @@ import { BrushWidth } from 'features/controlLayers/components/BrushWidth'; import ControlLayersSettingsPopover from 'features/controlLayers/components/ControlLayersSettingsPopover'; import { EraserWidth } from 'features/controlLayers/components/EraserWidth'; import { FillColorPicker } from 'features/controlLayers/components/FillColorPicker'; +import { NewSessionButton } from 'features/controlLayers/components/NewSessionButton'; import { ResetCanvasButton } from 'features/controlLayers/components/ResetCanvasButton'; import { ToolChooser } from 'features/controlLayers/components/ToolChooser'; import { UndoRedoButtonGroup } from 'features/controlLayers/components/UndoRedoButtonGroup'; @@ -32,6 +33,7 @@ export const ControlLayersToolbar = memo(() => { + diff --git a/invokeai/frontend/web/src/features/controlLayers/components/NewSessionButton.tsx b/invokeai/frontend/web/src/features/controlLayers/components/NewSessionButton.tsx new file mode 100644 index 0000000000..6befb0a59f --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/NewSessionButton.tsx @@ -0,0 +1,16 @@ +import { Button } from '@invoke-ai/ui-library'; +import { useAppDispatch } from 'app/store/storeHooks'; +import { sessionStarted } from 'features/controlLayers/store/canvasV2Slice'; +import { memo, useCallback } from 'react'; + +export const NewSessionButton = memo(() => { + const dispatch = useAppDispatch(); + + const onClick = useCallback(() => { + dispatch(sessionStarted()); + }, [dispatch]); + + return ; +}); + +NewSessionButton.displayName = 'NewSessionButton'; diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasBbox.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasBbox.ts index c6f22f3fe0..f5bc028a1b 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasBbox.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasBbox.ts @@ -205,9 +205,17 @@ export class CanvasBbox { } render() { + const session = this.manager.stateApi.getSession(); const bbox = this.manager.stateApi.getBbox(); const toolState = this.manager.stateApi.getToolState(); + if (!session.isActive) { + this.group.listening(false); + this.group.visible(false); + return; + } + + this.group.visible(true); this.group.listening(toolState.selected === 'bbox'); this.rect.setAttrs({ x: bbox.rect.x, diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts index 54681d5132..804faa45e4 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts @@ -265,7 +265,8 @@ export class CanvasManager { if ( this.isFirstRender || state.bbox !== this.prevState.bbox || - state.tool.selected !== this.prevState.tool.selected + state.tool.selected !== this.prevState.tool.selected || + state.session.isActive !== this.prevState.session.isActive ) { log.debug('Rendering generation bbox'); this.preview.bbox.render(); diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStagingArea.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStagingArea.ts index b4f1c25a16..8623c09752 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStagingArea.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStagingArea.ts @@ -20,7 +20,7 @@ export class CanvasStagingArea { } async render() { - const stagingArea = this.manager.stateApi.getStagingAreaState(); + const stagingArea = this.manager.stateApi.getSession(); const bbox = this.manager.stateApi.getBbox(); const shouldShowStagedImage = this.manager.stateApi.getShouldShowStagedImage(); const lastProgressEvent = this.manager.stateApi.getLastProgressEvent(); diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApi.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApi.ts index bfbc58ae9e..d485290c15 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApi.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasStateApi.ts @@ -231,7 +231,7 @@ export class CanvasStateApi { getMaskOpacity = () => { return this.getState().settings.maskOpacity; }; - getStagingAreaState = () => { + getSession = () => { return this.getState().session; }; getIsSelected = (id: string) => { diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/util.ts b/invokeai/frontend/web/src/features/controlLayers/konva/util.ts index c5971d7b99..e729306ca0 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/util.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/util.ts @@ -353,7 +353,7 @@ export function getCompositeLayerStageClone(arg: { manager: CanvasManager }): Ko export function getGenerationMode(arg: { manager: CanvasManager }): GenerationMode { const { manager } = arg; - const { x, y, width, height } = manager.stateApi.getBbox(); + const { x, y, width, height } = manager.stateApi.getBbox().rect; const inpaintMaskLayer = getInpaintMaskLayerClone(arg); const inpaintMaskImageData = konvaNodeToImageData(inpaintMaskLayer, { x, y, width, height }); const inpaintMaskTransparency = getImageDataTransparency(inpaintMaskImageData); diff --git a/invokeai/frontend/web/src/features/parameters/components/DocumentSize/DocumentSize.tsx b/invokeai/frontend/web/src/features/parameters/components/DocumentSize/DocumentSize.tsx index 97992f093c..3d710bc47f 100644 --- a/invokeai/frontend/web/src/features/parameters/components/DocumentSize/DocumentSize.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/DocumentSize/DocumentSize.tsx @@ -1,8 +1,8 @@ import type { FormLabelProps } from '@invoke-ai/ui-library'; import { Flex, FormControlGroup } from '@invoke-ai/ui-library'; +import { CanvasResizer } from 'features/controlLayers/components/CanvasResizer'; import { ParamHeight } from 'features/parameters/components/Core/ParamHeight'; import { ParamWidth } from 'features/parameters/components/Core/ParamWidth'; -import { AspectRatioIconPreview } from 'features/parameters/components/DocumentSize/AspectRatioIconPreview'; import { AspectRatioSelect } from 'features/parameters/components/DocumentSize/AspectRatioSelect'; import { LockAspectRatioButton } from 'features/parameters/components/DocumentSize/LockAspectRatioButton'; import { SetOptimalSizeButton } from 'features/parameters/components/DocumentSize/SetOptimalSizeButton'; @@ -24,8 +24,8 @@ export const DocumentSize = memo(() => { - - + + );