mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
UNDO ME WIP
This commit is contained in:
parent
c49b90e621
commit
78b4562184
@ -18,7 +18,7 @@ export const addEnqueueRequestedLinear = (startAppListening: AppStartListening)
|
|||||||
const { prepend } = action.payload;
|
const { prepend } = action.payload;
|
||||||
|
|
||||||
let didStartStaging = false;
|
let didStartStaging = false;
|
||||||
if (!state.canvasV2.session.isStaging) {
|
if (!state.canvasV2.session.isStaging && state.canvasV2.session.isActive) {
|
||||||
dispatch(sessionStartedStaging());
|
dispatch(sessionStartedStaging());
|
||||||
didStartStaging = true;
|
didStartStaging = true;
|
||||||
}
|
}
|
||||||
|
@ -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<ResizeDirection>('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 (
|
||||||
|
<Flex p={2}>
|
||||||
|
<Grid gridTemplateRows="1fr 1fr 1fr" gridTemplateColumns="1fr 1fr 1fr" gap={2}>
|
||||||
|
<GridItem>
|
||||||
|
<IconButton
|
||||||
|
onClick={setDirUpLeft}
|
||||||
|
aria-label="up-left"
|
||||||
|
icon={<PiArrowUpLeftBold />}
|
||||||
|
variant={resizeDirection === 'up-left' ? 'solid' : 'ghost'}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem>
|
||||||
|
<IconButton
|
||||||
|
onClick={setDirUp}
|
||||||
|
aria-label="up"
|
||||||
|
icon={<PiArrowUpBold />}
|
||||||
|
variant={resizeDirection === 'up' ? 'solid' : 'ghost'}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem>
|
||||||
|
<IconButton
|
||||||
|
onClick={setDirUpRight}
|
||||||
|
aria-label="up-right"
|
||||||
|
icon={<PiArrowUpRightBold />}
|
||||||
|
variant={resizeDirection === 'up-right' ? 'solid' : 'ghost'}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem>
|
||||||
|
<IconButton
|
||||||
|
onClick={setDirLeft}
|
||||||
|
aria-label="left"
|
||||||
|
icon={<PiArrowLeftBold />}
|
||||||
|
variant={resizeDirection === 'left' ? 'solid' : 'ghost'}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem>
|
||||||
|
<IconButton
|
||||||
|
onClick={setDirCenterOut}
|
||||||
|
aria-label="center-out"
|
||||||
|
icon={<PiSquareBold />}
|
||||||
|
variant={resizeDirection === 'center-out' ? 'solid' : 'ghost'}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem>
|
||||||
|
<IconButton
|
||||||
|
onClick={setDirRight}
|
||||||
|
aria-label="right"
|
||||||
|
icon={<PiArrowRightBold />}
|
||||||
|
variant={resizeDirection === 'right' ? 'solid' : 'ghost'}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem>
|
||||||
|
<IconButton
|
||||||
|
onClick={setDirDownLeft}
|
||||||
|
aria-label="down-left"
|
||||||
|
icon={<PiArrowDownLeftBold />}
|
||||||
|
variant={resizeDirection === 'down-left' ? 'solid' : 'ghost'}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem>
|
||||||
|
<IconButton
|
||||||
|
onClick={setDirDown}
|
||||||
|
aria-label="down"
|
||||||
|
icon={<PiArrowDownBold />}
|
||||||
|
variant={resizeDirection === 'down' ? 'solid' : 'ghost'}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem>
|
||||||
|
<IconButton
|
||||||
|
onClick={setDirDownRight}
|
||||||
|
aria-label="down-right"
|
||||||
|
icon={<PiArrowDownRightBold />}
|
||||||
|
variant={resizeDirection === 'down-right' ? 'solid' : 'ghost'}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
</Grid>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
CanvasResizer.displayName = 'CanvasResizer';
|
@ -21,6 +21,9 @@ export const ControlLayersEditor = memo(() => {
|
|||||||
<Flex position="absolute" bottom={2} gap={2} align="center" justify="center">
|
<Flex position="absolute" bottom={2} gap={2} align="center" justify="center">
|
||||||
<StagingAreaToolbar />
|
<StagingAreaToolbar />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
{/* <Flex position="absolute" top={0} right={0} bottom={0} left={0} align="center" justify="center">
|
||||||
|
<CanvasResizer />
|
||||||
|
</Flex> */}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -5,6 +5,7 @@ import { BrushWidth } from 'features/controlLayers/components/BrushWidth';
|
|||||||
import ControlLayersSettingsPopover from 'features/controlLayers/components/ControlLayersSettingsPopover';
|
import ControlLayersSettingsPopover from 'features/controlLayers/components/ControlLayersSettingsPopover';
|
||||||
import { EraserWidth } from 'features/controlLayers/components/EraserWidth';
|
import { EraserWidth } from 'features/controlLayers/components/EraserWidth';
|
||||||
import { FillColorPicker } from 'features/controlLayers/components/FillColorPicker';
|
import { FillColorPicker } from 'features/controlLayers/components/FillColorPicker';
|
||||||
|
import { NewSessionButton } from 'features/controlLayers/components/NewSessionButton';
|
||||||
import { ResetCanvasButton } from 'features/controlLayers/components/ResetCanvasButton';
|
import { ResetCanvasButton } from 'features/controlLayers/components/ResetCanvasButton';
|
||||||
import { ToolChooser } from 'features/controlLayers/components/ToolChooser';
|
import { ToolChooser } from 'features/controlLayers/components/ToolChooser';
|
||||||
import { UndoRedoButtonGroup } from 'features/controlLayers/components/UndoRedoButtonGroup';
|
import { UndoRedoButtonGroup } from 'features/controlLayers/components/UndoRedoButtonGroup';
|
||||||
@ -32,6 +33,7 @@ export const ControlLayersToolbar = memo(() => {
|
|||||||
<UndoRedoButtonGroup />
|
<UndoRedoButtonGroup />
|
||||||
<ControlLayersSettingsPopover />
|
<ControlLayersSettingsPopover />
|
||||||
<ResetCanvasButton />
|
<ResetCanvasButton />
|
||||||
|
<NewSessionButton />
|
||||||
<ViewerToggleMenu />
|
<ViewerToggleMenu />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@ -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 <Button onClick={onClick}>New</Button>;
|
||||||
|
});
|
||||||
|
|
||||||
|
NewSessionButton.displayName = 'NewSessionButton';
|
@ -205,9 +205,17 @@ export class CanvasBbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const session = this.manager.stateApi.getSession();
|
||||||
const bbox = this.manager.stateApi.getBbox();
|
const bbox = this.manager.stateApi.getBbox();
|
||||||
const toolState = this.manager.stateApi.getToolState();
|
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.group.listening(toolState.selected === 'bbox');
|
||||||
this.rect.setAttrs({
|
this.rect.setAttrs({
|
||||||
x: bbox.rect.x,
|
x: bbox.rect.x,
|
||||||
|
@ -265,7 +265,8 @@ export class CanvasManager {
|
|||||||
if (
|
if (
|
||||||
this.isFirstRender ||
|
this.isFirstRender ||
|
||||||
state.bbox !== this.prevState.bbox ||
|
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');
|
log.debug('Rendering generation bbox');
|
||||||
this.preview.bbox.render();
|
this.preview.bbox.render();
|
||||||
|
@ -20,7 +20,7 @@ export class CanvasStagingArea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async render() {
|
async render() {
|
||||||
const stagingArea = this.manager.stateApi.getStagingAreaState();
|
const stagingArea = this.manager.stateApi.getSession();
|
||||||
const bbox = this.manager.stateApi.getBbox();
|
const bbox = this.manager.stateApi.getBbox();
|
||||||
const shouldShowStagedImage = this.manager.stateApi.getShouldShowStagedImage();
|
const shouldShowStagedImage = this.manager.stateApi.getShouldShowStagedImage();
|
||||||
const lastProgressEvent = this.manager.stateApi.getLastProgressEvent();
|
const lastProgressEvent = this.manager.stateApi.getLastProgressEvent();
|
||||||
|
@ -231,7 +231,7 @@ export class CanvasStateApi {
|
|||||||
getMaskOpacity = () => {
|
getMaskOpacity = () => {
|
||||||
return this.getState().settings.maskOpacity;
|
return this.getState().settings.maskOpacity;
|
||||||
};
|
};
|
||||||
getStagingAreaState = () => {
|
getSession = () => {
|
||||||
return this.getState().session;
|
return this.getState().session;
|
||||||
};
|
};
|
||||||
getIsSelected = (id: string) => {
|
getIsSelected = (id: string) => {
|
||||||
|
@ -353,7 +353,7 @@ export function getCompositeLayerStageClone(arg: { manager: CanvasManager }): Ko
|
|||||||
|
|
||||||
export function getGenerationMode(arg: { manager: CanvasManager }): GenerationMode {
|
export function getGenerationMode(arg: { manager: CanvasManager }): GenerationMode {
|
||||||
const { manager } = arg;
|
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 inpaintMaskLayer = getInpaintMaskLayerClone(arg);
|
||||||
const inpaintMaskImageData = konvaNodeToImageData(inpaintMaskLayer, { x, y, width, height });
|
const inpaintMaskImageData = konvaNodeToImageData(inpaintMaskLayer, { x, y, width, height });
|
||||||
const inpaintMaskTransparency = getImageDataTransparency(inpaintMaskImageData);
|
const inpaintMaskTransparency = getImageDataTransparency(inpaintMaskImageData);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import type { FormLabelProps } from '@invoke-ai/ui-library';
|
import type { FormLabelProps } from '@invoke-ai/ui-library';
|
||||||
import { Flex, FormControlGroup } 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 { ParamHeight } from 'features/parameters/components/Core/ParamHeight';
|
||||||
import { ParamWidth } from 'features/parameters/components/Core/ParamWidth';
|
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 { AspectRatioSelect } from 'features/parameters/components/DocumentSize/AspectRatioSelect';
|
||||||
import { LockAspectRatioButton } from 'features/parameters/components/DocumentSize/LockAspectRatioButton';
|
import { LockAspectRatioButton } from 'features/parameters/components/DocumentSize/LockAspectRatioButton';
|
||||||
import { SetOptimalSizeButton } from 'features/parameters/components/DocumentSize/SetOptimalSizeButton';
|
import { SetOptimalSizeButton } from 'features/parameters/components/DocumentSize/SetOptimalSizeButton';
|
||||||
@ -24,8 +24,8 @@ export const DocumentSize = memo(() => {
|
|||||||
<ParamHeight />
|
<ParamHeight />
|
||||||
</FormControlGroup>
|
</FormControlGroup>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex w="108px" h="108px" flexShrink={0} flexGrow={0}>
|
<Flex w="108px" h="108px" flexShrink={0} flexGrow={0} bg="base.850" alignItems="center" justifyContent="center">
|
||||||
<AspectRatioIconPreview />
|
<CanvasResizer />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user