mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Removes all references to split inpainting/outpainting canvas
This commit is contained in:
parent
15dd1339d2
commit
e3efcc620c
@ -4,20 +4,20 @@ import { RootState } from 'app/store';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { OptionsState } from 'features/options/optionsSlice';
|
||||
import { SystemState } from 'features/system/systemSlice';
|
||||
import { baseCanvasImageSelector } from 'features/canvas/canvasSlice';
|
||||
import { validateSeedWeights } from 'common/util/seedWeightPairs';
|
||||
import { initialCanvasImageSelector } from 'features/canvas/canvasSlice';
|
||||
|
||||
export const readinessSelector = createSelector(
|
||||
[
|
||||
(state: RootState) => state.options,
|
||||
(state: RootState) => state.system,
|
||||
baseCanvasImageSelector,
|
||||
initialCanvasImageSelector,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(
|
||||
options: OptionsState,
|
||||
system: SystemState,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
activeTabName
|
||||
) => {
|
||||
const {
|
||||
@ -44,7 +44,7 @@ export const readinessSelector = createSelector(
|
||||
reasonsWhyNotReady.push('No initial image selected');
|
||||
}
|
||||
|
||||
if (activeTabName === 'inpainting' && !baseCanvasImage) {
|
||||
if (activeTabName === 'inpainting' && !initialCanvasImage) {
|
||||
isReady = false;
|
||||
reasonsWhyNotReady.push('No inpainting image selected');
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
import { InvokeTabName } from 'features/tabs/InvokeTabs';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
import { RootState } from 'app/store';
|
||||
import { baseCanvasImageSelector } from 'features/canvas/canvasSlice';
|
||||
import { initialCanvasImageSelector } from 'features/canvas/canvasSlice';
|
||||
|
||||
/**
|
||||
* Returns an object containing all functions which use `socketio.emit()`.
|
||||
@ -55,8 +55,8 @@ const makeSocketIOEmitters = (
|
||||
};
|
||||
|
||||
if (generationMode === 'inpainting') {
|
||||
const baseCanvasImage = baseCanvasImageSelector(getState());
|
||||
const imageUrl = baseCanvasImage?.image.url;
|
||||
const initialCanvasImage = initialCanvasImageSelector(getState());
|
||||
const imageUrl = initialCanvasImage?.image.url;
|
||||
|
||||
if (!imageUrl) {
|
||||
dispatch(
|
||||
|
@ -119,7 +119,7 @@ export const frontendToBackendParameters = (
|
||||
stageScale,
|
||||
isMaskEnabled,
|
||||
shouldPreserveMaskedArea,
|
||||
} = canvasState[canvasState.currentCanvas];
|
||||
} = canvasState;
|
||||
|
||||
const boundingBox = {
|
||||
...boundingBoxCoordinates,
|
||||
|
@ -5,14 +5,11 @@ import { Layer, Stage } from 'react-konva';
|
||||
import { Stage as StageType } from 'konva/lib/Stage';
|
||||
|
||||
// app
|
||||
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import {
|
||||
baseCanvasImageSelector,
|
||||
currentCanvasSelector,
|
||||
initialCanvasImageSelector,
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
outpaintingCanvasSelector,
|
||||
setStageCoordinates,
|
||||
setStageScale,
|
||||
shouldLockToInitialImageSelector,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
|
||||
@ -39,29 +36,21 @@ import IAICanvasIntermediateImage from './IAICanvasIntermediateImage';
|
||||
import IAICanvasStatusText from './IAICanvasStatusText';
|
||||
import IAICanvasStagingArea from './IAICanvasStagingArea';
|
||||
import IAICanvasStagingAreaToolbar from './IAICanvasStagingAreaToolbar';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import {
|
||||
CANVAS_SCALE_BY,
|
||||
MAX_CANVAS_SCALE,
|
||||
MIN_CANVAS_SCALE,
|
||||
} from './util/constants';
|
||||
|
||||
const canvasSelector = createSelector(
|
||||
const selector = createSelector(
|
||||
[
|
||||
shouldLockToInitialImageSelector,
|
||||
currentCanvasSelector,
|
||||
outpaintingCanvasSelector,
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
activeTabNameSelector,
|
||||
baseCanvasImageSelector,
|
||||
initialCanvasImageSelector,
|
||||
],
|
||||
(
|
||||
shouldLockToInitialImage,
|
||||
currentCanvas,
|
||||
outpaintingCanvas,
|
||||
canvas,
|
||||
isStaging,
|
||||
activeTabName,
|
||||
baseCanvasImage
|
||||
initialCanvasImage
|
||||
) => {
|
||||
const {
|
||||
isMaskEnabled,
|
||||
@ -75,10 +64,8 @@ const canvasSelector = createSelector(
|
||||
tool,
|
||||
isMovingStage,
|
||||
shouldShowIntermediates,
|
||||
minimumStageScale,
|
||||
} = currentCanvas;
|
||||
|
||||
const { shouldShowGrid } = outpaintingCanvas;
|
||||
shouldShowGrid,
|
||||
} = canvas;
|
||||
|
||||
let stageCursor: string | undefined = '';
|
||||
|
||||
@ -110,9 +97,7 @@ const canvasSelector = createSelector(
|
||||
isStaging,
|
||||
shouldShowIntermediates,
|
||||
shouldLockToInitialImage,
|
||||
activeTabName,
|
||||
minimumStageScale,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -141,11 +126,8 @@ const IAICanvas = () => {
|
||||
isStaging,
|
||||
shouldShowIntermediates,
|
||||
shouldLockToInitialImage,
|
||||
activeTabName,
|
||||
minimumStageScale,
|
||||
baseCanvasImage,
|
||||
} = useAppSelector(canvasSelector);
|
||||
const dispatch = useAppDispatch();
|
||||
initialCanvasImage,
|
||||
} = useAppSelector(selector);
|
||||
useCanvasHotkeys();
|
||||
|
||||
// set the closure'd refs
|
||||
@ -172,17 +154,17 @@ const IAICanvas = () => {
|
||||
|
||||
const dragBoundFunc = useCallback(
|
||||
(newCoordinates: Vector2d) => {
|
||||
if (shouldLockToInitialImage && baseCanvasImage) {
|
||||
if (shouldLockToInitialImage && initialCanvasImage) {
|
||||
newCoordinates.x = _.clamp(
|
||||
newCoordinates.x,
|
||||
stageDimensions.width -
|
||||
Math.floor(baseCanvasImage.width * stageScale),
|
||||
Math.floor(initialCanvasImage.width * stageScale),
|
||||
0
|
||||
);
|
||||
newCoordinates.y = _.clamp(
|
||||
newCoordinates.y,
|
||||
stageDimensions.height -
|
||||
Math.floor(baseCanvasImage.height * stageScale),
|
||||
Math.floor(initialCanvasImage.height * stageScale),
|
||||
0
|
||||
);
|
||||
}
|
||||
@ -190,7 +172,7 @@ const IAICanvas = () => {
|
||||
return newCoordinates;
|
||||
},
|
||||
[
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
shouldLockToInitialImage,
|
||||
stageDimensions.height,
|
||||
stageDimensions.width,
|
||||
|
@ -6,15 +6,11 @@ import { Vector2d } from 'konva/lib/types';
|
||||
import _ from 'lodash';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { Group, Rect, Transformer } from 'react-konva';
|
||||
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { roundToMultiple } from 'common/util/roundDownToMultiple';
|
||||
import {
|
||||
roundDownToMultiple,
|
||||
roundToMultiple,
|
||||
} from 'common/util/roundDownToMultiple';
|
||||
import {
|
||||
baseCanvasImageSelector,
|
||||
currentCanvasSelector,
|
||||
outpaintingCanvasSelector,
|
||||
initialCanvasImageSelector,
|
||||
canvasSelector,
|
||||
setBoundingBoxCoordinates,
|
||||
setBoundingBoxDimensions,
|
||||
setIsMouseOverBoundingBox,
|
||||
@ -27,17 +23,10 @@ import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
|
||||
const boundingBoxPreviewSelector = createSelector(
|
||||
shouldLockToInitialImageSelector,
|
||||
currentCanvasSelector,
|
||||
outpaintingCanvasSelector,
|
||||
baseCanvasImageSelector,
|
||||
canvasSelector,
|
||||
initialCanvasImageSelector,
|
||||
activeTabNameSelector,
|
||||
(
|
||||
shouldLockToInitialImage,
|
||||
currentCanvas,
|
||||
outpaintingCanvas,
|
||||
baseCanvasImage,
|
||||
activeTabName
|
||||
) => {
|
||||
(shouldLockToInitialImage, canvas, initialCanvasImage, activeTabName) => {
|
||||
const {
|
||||
boundingBoxCoordinates,
|
||||
boundingBoxDimensions,
|
||||
@ -50,9 +39,8 @@ const boundingBoxPreviewSelector = createSelector(
|
||||
shouldDarkenOutsideBoundingBox,
|
||||
tool,
|
||||
stageCoordinates,
|
||||
} = currentCanvas;
|
||||
|
||||
const { shouldSnapToGrid } = outpaintingCanvas;
|
||||
shouldSnapToGrid,
|
||||
} = canvas;
|
||||
|
||||
return {
|
||||
boundingBoxCoordinates,
|
||||
@ -64,7 +52,7 @@ const boundingBoxPreviewSelector = createSelector(
|
||||
isTransformingBoundingBox,
|
||||
stageDimensions,
|
||||
stageScale,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
activeTabName,
|
||||
shouldSnapToGrid,
|
||||
tool,
|
||||
@ -98,7 +86,7 @@ const IAICanvasBoundingBox = (props: IAICanvasBoundingBoxPreviewProps) => {
|
||||
stageCoordinates,
|
||||
stageDimensions,
|
||||
stageScale,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
activeTabName,
|
||||
shouldSnapToGrid,
|
||||
tool,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
setBrushColor,
|
||||
setBrushSize,
|
||||
@ -16,9 +16,9 @@ import IAISlider from 'common/components/IAISlider';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
|
||||
export const selector = createSelector(
|
||||
[currentCanvasSelector, isStagingSelector],
|
||||
(currentCanvas, isStaging) => {
|
||||
const { brushColor, brushSize, tool } = currentCanvas;
|
||||
[canvasSelector, isStagingSelector],
|
||||
(canvas, isStaging) => {
|
||||
const { brushColor, brushSize, tool } = canvas;
|
||||
|
||||
return {
|
||||
tool,
|
||||
|
@ -3,12 +3,12 @@ import { GroupConfig } from 'konva/lib/Group';
|
||||
import _ from 'lodash';
|
||||
import { Circle, Group } from 'react-konva';
|
||||
import { useAppSelector } from 'app/store';
|
||||
import { currentCanvasSelector } from 'features/canvas/canvasSlice';
|
||||
import { canvasSelector } from 'features/canvas/canvasSlice';
|
||||
import { rgbaColorToString } from './util/colorToString';
|
||||
|
||||
const canvasBrushPreviewSelector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas) => {
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
const {
|
||||
cursorPosition,
|
||||
stageDimensions: { width, height },
|
||||
@ -22,7 +22,7 @@ const canvasBrushPreviewSelector = createSelector(
|
||||
isMovingBoundingBox,
|
||||
isTransformingBoundingBox,
|
||||
stageScale,
|
||||
} = currentCanvas;
|
||||
} = canvas;
|
||||
|
||||
return {
|
||||
cursorPosition,
|
||||
|
@ -10,28 +10,17 @@ import IAICanvasLockBoundingBoxControl from './IAICanvasControls/IAICanvasLockBo
|
||||
import IAICanvasShowHideBoundingBoxControl from './IAICanvasControls/IAICanvasShowHideBoundingBoxControl';
|
||||
import ImageUploaderIconButton from 'common/components/ImageUploaderIconButton';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
outpaintingCanvasSelector,
|
||||
OutpaintingCanvasState,
|
||||
} from './canvasSlice';
|
||||
import { RootState } from 'app/store';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { OptionsState } from 'features/options/optionsSlice';
|
||||
import _ from 'lodash';
|
||||
import { canvasSelector } from './canvasSlice';
|
||||
|
||||
export const canvasControlsSelector = createSelector(
|
||||
[
|
||||
outpaintingCanvasSelector,
|
||||
(state: RootState) => state.options,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(
|
||||
outpaintingCanvas: OutpaintingCanvasState,
|
||||
options: OptionsState,
|
||||
activeTabName
|
||||
) => {
|
||||
[(state: RootState) => state.options, canvasSelector, activeTabNameSelector],
|
||||
(options: OptionsState, canvas, activeTabName) => {
|
||||
const { stageScale, boundingBoxCoordinates, boundingBoxDimensions } =
|
||||
outpaintingCanvas;
|
||||
canvas;
|
||||
return {
|
||||
activeTabName,
|
||||
stageScale,
|
||||
|
@ -9,7 +9,7 @@ import IAISlider from 'common/components/IAISlider';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
setBrushSize,
|
||||
setShouldShowBrushPreview,
|
||||
setTool,
|
||||
@ -19,9 +19,9 @@ import _ from 'lodash';
|
||||
import IAICanvasMaskColorPicker from './IAICanvasMaskControls/IAICanvasMaskColorPicker';
|
||||
|
||||
const inpaintingBrushSelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas, activeTabName) => {
|
||||
const { tool, brushSize } = currentCanvas;
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const { tool, brushSize } = canvas;
|
||||
|
||||
return {
|
||||
tool,
|
||||
|
@ -3,15 +3,15 @@ import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { FaEraser } from 'react-icons/fa';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { currentCanvasSelector, setTool } from 'features/canvas/canvasSlice';
|
||||
import { canvasSelector, setTool } from 'features/canvas/canvasSlice';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
|
||||
const eraserSelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas, activeTabName) => {
|
||||
const { tool, isMaskEnabled } = currentCanvas;
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const { tool, isMaskEnabled } = canvas;
|
||||
|
||||
return {
|
||||
tool,
|
||||
|
@ -2,16 +2,16 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { currentCanvasSelector, setTool } from 'features/canvas/canvasSlice';
|
||||
import { canvasSelector, setTool } from 'features/canvas/canvasSlice';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { BsEraser } from 'react-icons/bs';
|
||||
|
||||
const imageEraserSelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas, activeTabName) => {
|
||||
const { tool, isMaskEnabled } = currentCanvas;
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const { tool, isMaskEnabled } = canvas;
|
||||
|
||||
return {
|
||||
tool,
|
||||
|
@ -2,17 +2,16 @@ import { FaLock, FaUnlock } from 'react-icons/fa';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
canvasSelector,
|
||||
setShouldLockBoundingBox,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import _ from 'lodash';
|
||||
|
||||
const canvasLockBoundingBoxSelector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas: GenericCanvasState) => {
|
||||
const { shouldLockBoundingBox } = currentCanvas;
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
const { shouldLockBoundingBox } = canvas;
|
||||
|
||||
return {
|
||||
shouldLockBoundingBox,
|
||||
|
@ -1,11 +1,7 @@
|
||||
import { RgbaColor } from 'react-colorful';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIColorPicker from 'common/components/IAIColorPicker';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
setMaskColor,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import { canvasSelector, setMaskColor } from 'features/canvas/canvasSlice';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
@ -13,9 +9,9 @@ import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
const selector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas: GenericCanvasState, activeTabName) => {
|
||||
const { brushColor } = currentCanvas;
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const { brushColor } = canvas;
|
||||
|
||||
return {
|
||||
brushColor,
|
||||
|
@ -5,10 +5,8 @@ import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import {
|
||||
clearMask,
|
||||
currentCanvasSelector,
|
||||
InpaintingCanvasState,
|
||||
canvasSelector,
|
||||
isCanvasMaskLine,
|
||||
OutpaintingCanvasState,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
|
||||
import _ from 'lodash';
|
||||
@ -16,12 +14,12 @@ import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
|
||||
const canvasMaskClearSelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas, activeTabName) => {
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const {
|
||||
isMaskEnabled,
|
||||
layerState: { objects },
|
||||
} = currentCanvas as InpaintingCanvasState | OutpaintingCanvasState;
|
||||
} = canvas;
|
||||
|
||||
return {
|
||||
isMaskEnabled,
|
||||
|
@ -5,11 +5,7 @@ import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIColorPicker from 'common/components/IAIColorPicker';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import IAIPopover from 'common/components/IAIPopover';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
setMaskColor,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import { canvasSelector, setMaskColor } from 'features/canvas/canvasSlice';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
@ -17,9 +13,9 @@ import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
const maskColorPickerSelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas: GenericCanvasState, activeTabName) => {
|
||||
const { isMaskEnabled, maskColor } = currentCanvas;
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const { isMaskEnabled, maskColor } = canvas;
|
||||
|
||||
return {
|
||||
isMaskEnabled,
|
||||
|
@ -3,8 +3,7 @@ import { MdInvertColors, MdInvertColorsOff } from 'react-icons/md';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
canvasSelector,
|
||||
setShouldPreserveMaskedArea,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
|
||||
@ -13,9 +12,9 @@ import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
const canvasMaskInvertSelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas: GenericCanvasState, activeTabName) => {
|
||||
const { isMaskEnabled, shouldPreserveMaskedArea } = currentCanvas;
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const { isMaskEnabled, shouldPreserveMaskedArea } = canvas;
|
||||
|
||||
return {
|
||||
shouldPreserveMaskedArea,
|
||||
@ -31,9 +30,8 @@ const canvasMaskInvertSelector = createSelector(
|
||||
);
|
||||
|
||||
export default function IAICanvasMaskInvertControl() {
|
||||
const { shouldPreserveMaskedArea, isMaskEnabled, activeTabName } = useAppSelector(
|
||||
canvasMaskInvertSelector
|
||||
);
|
||||
const { shouldPreserveMaskedArea, isMaskEnabled, activeTabName } =
|
||||
useAppSelector(canvasMaskInvertSelector);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleToggleShouldInvertMask = () =>
|
||||
|
@ -4,18 +4,14 @@ import { createSelector } from 'reselect';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
setIsMaskEnabled,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import { canvasSelector, setIsMaskEnabled } from 'features/canvas/canvasSlice';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
const canvasMaskVisibilitySelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas: GenericCanvasState, activeTabName) => {
|
||||
const { isMaskEnabled } = currentCanvas;
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const { isMaskEnabled } = canvas;
|
||||
|
||||
return { isMaskEnabled, activeTabName };
|
||||
},
|
||||
|
@ -4,14 +4,14 @@ import { FaRedo } from 'react-icons/fa';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { currentCanvasSelector, redo } from 'features/canvas/canvasSlice';
|
||||
import { canvasSelector, redo } from 'features/canvas/canvasSlice';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
const canvasRedoSelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas, activeTabName) => {
|
||||
const { futureLayerStates } = currentCanvas;
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const { futureLayerStates } = canvas;
|
||||
|
||||
return {
|
||||
canRedo: futureLayerStates.length > 0,
|
||||
|
@ -2,17 +2,16 @@ import { FaVectorSquare } from 'react-icons/fa';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
canvasSelector,
|
||||
setShouldShowBoundingBox,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import _ from 'lodash';
|
||||
|
||||
const canvasShowHideBoundingBoxControlSelector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas: GenericCanvasState) => {
|
||||
const { shouldShowBoundingBox } = currentCanvas;
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
const { shouldShowBoundingBox } = canvas;
|
||||
|
||||
return {
|
||||
shouldShowBoundingBox,
|
||||
|
@ -3,13 +3,13 @@ import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { FaUndo } from 'react-icons/fa';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { currentCanvasSelector, undo } from 'features/canvas/canvasSlice';
|
||||
import { canvasSelector, undo } from 'features/canvas/canvasSlice';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
|
||||
const canvasUndoSelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const { pastLayerStates } = canvas;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
setEraserSize,
|
||||
setTool,
|
||||
@ -15,9 +15,9 @@ import { Flex } from '@chakra-ui/react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
export const selector = createSelector(
|
||||
[currentCanvasSelector, isStagingSelector],
|
||||
(currentCanvas, isStaging) => {
|
||||
const { eraserSize, tool } = currentCanvas;
|
||||
[canvasSelector, isStagingSelector],
|
||||
(canvas, isStaging) => {
|
||||
const { eraserSize, tool } = canvas;
|
||||
|
||||
return {
|
||||
tool,
|
||||
|
@ -4,22 +4,14 @@ import { useColorMode } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { ReactNode, useCallback, useLayoutEffect, useState } from 'react';
|
||||
import { Group, Line as KonvaLine } from 'react-konva';
|
||||
import { currentCanvasSelector } from './canvasSlice';
|
||||
import useUnscaleCanvasValue from './hooks/useUnscaleCanvasValue';
|
||||
import { stageRef } from './IAICanvas';
|
||||
import { canvasSelector } from './canvasSlice';
|
||||
|
||||
const selector = createSelector(
|
||||
[currentCanvasSelector],
|
||||
(currentCanvas) => {
|
||||
const { stageScale, stageCoordinates, stageDimensions } = currentCanvas;
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const { stageScale, stageCoordinates, stageDimensions } = canvas;
|
||||
return { stageScale, stageCoordinates, stageDimensions };
|
||||
},
|
||||
{
|
||||
@ -31,7 +23,6 @@ const selector = createSelector(
|
||||
|
||||
const IAICanvasGrid = () => {
|
||||
const { colorMode } = useColorMode();
|
||||
// const unscale = useUnscaleCanvasValue();
|
||||
const { stageScale, stageCoordinates, stageDimensions } =
|
||||
useAppSelector(selector);
|
||||
const [gridLines, setGridLines] = useState<ReactNode[]>([]);
|
||||
|
@ -2,7 +2,7 @@ import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
clearMask,
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
setIsMaskEnabled,
|
||||
setLayer,
|
||||
setMaskColor,
|
||||
@ -18,9 +18,10 @@ import IAIColorPicker from 'common/components/IAIColorPicker';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
|
||||
export const selector = createSelector(
|
||||
[currentCanvasSelector],
|
||||
(currentCanvas) => {
|
||||
const { maskColor, layer, isMaskEnabled, shouldPreserveMaskedArea } = currentCanvas;
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const { maskColor, layer, isMaskEnabled, shouldPreserveMaskedArea } =
|
||||
canvas;
|
||||
|
||||
return {
|
||||
layer,
|
||||
@ -63,7 +64,9 @@ const IAICanvasMaskButtonPopover = () => {
|
||||
<IAICheckbox
|
||||
label="Preserve Masked Area"
|
||||
isChecked={shouldPreserveMaskedArea}
|
||||
onChange={(e) => dispatch(setShouldPreserveMaskedArea(e.target.checked))}
|
||||
onChange={(e) =>
|
||||
dispatch(setShouldPreserveMaskedArea(e.target.checked))
|
||||
}
|
||||
/>
|
||||
<IAIColorPicker
|
||||
color={maskColor}
|
||||
|
@ -2,21 +2,16 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store';
|
||||
import { RectConfig } from 'konva/lib/shapes/Rect';
|
||||
import { Rect } from 'react-konva';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
InpaintingCanvasState,
|
||||
OutpaintingCanvasState,
|
||||
} from './canvasSlice';
|
||||
import { canvasSelector } from './canvasSlice';
|
||||
|
||||
import { rgbaColorToString } from './util/colorToString';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import Konva from 'konva';
|
||||
|
||||
export const canvasMaskCompositerSelector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas) => {
|
||||
const { maskColor, stageCoordinates, stageDimensions, stageScale } =
|
||||
currentCanvas as InpaintingCanvasState | OutpaintingCanvasState;
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
const { maskColor, stageCoordinates, stageDimensions, stageScale } = canvas;
|
||||
|
||||
return {
|
||||
stageCoordinates,
|
||||
|
@ -2,13 +2,13 @@ import { GroupConfig } from 'konva/lib/Group';
|
||||
import { Group, Line } from 'react-konva';
|
||||
import { useAppSelector } from 'app/store';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { currentCanvasSelector, isCanvasMaskLine } from './canvasSlice';
|
||||
import { canvasSelector, isCanvasMaskLine } from './canvasSlice';
|
||||
import _ from 'lodash';
|
||||
|
||||
export const canvasLinesSelector = createSelector(
|
||||
[currentCanvasSelector],
|
||||
(currentCanvas) => {
|
||||
return { objects: currentCanvas.layerState.objects };
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
return { objects: canvas.layerState.objects };
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
|
@ -1,12 +1,9 @@
|
||||
import { createSelector, current } from '@reduxjs/toolkit';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store';
|
||||
import _ from 'lodash';
|
||||
import { Group, Line } from 'react-konva';
|
||||
import {
|
||||
baseCanvasImageSelector,
|
||||
// canvasClipSelector,
|
||||
// canvasModeSelector,
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
isCanvasBaseImage,
|
||||
isCanvasBaseLine,
|
||||
} from './canvasSlice';
|
||||
@ -14,9 +11,9 @@ import IAICanvasImage from './IAICanvasImage';
|
||||
import { rgbaColorToString } from './util/colorToString';
|
||||
|
||||
const selector = createSelector(
|
||||
[currentCanvasSelector],
|
||||
(currentCanvas) => {
|
||||
const { objects } = currentCanvas.layerState;
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const { objects } = canvas.layerState;
|
||||
|
||||
return {
|
||||
objects,
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { ButtonGroup } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
resizeAndScaleCanvas,
|
||||
isStagingSelector,
|
||||
resetCanvas,
|
||||
resetCanvasView,
|
||||
setShouldLockToInitialImage,
|
||||
setTool,
|
||||
canvasSelector,
|
||||
} from './canvasSlice';
|
||||
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import _ from 'lodash';
|
||||
import { canvasImageLayerRef, stageRef } from './IAICanvas';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
@ -33,15 +33,10 @@ import { mergeAndUploadCanvas } from './util/mergeAndUploadCanvas';
|
||||
import IAICheckbox from 'common/components/IAICheckbox';
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
export const canvasControlsSelector = createSelector(
|
||||
[
|
||||
(state: RootState) => state.canvas,
|
||||
currentCanvasSelector,
|
||||
isStagingSelector,
|
||||
],
|
||||
(canvas, currentCanvas, isStaging) => {
|
||||
const { shouldLockToInitialImage } = canvas;
|
||||
const { tool } = currentCanvas;
|
||||
export const selector = createSelector(
|
||||
[canvasSelector, isStagingSelector],
|
||||
(canvas, isStaging) => {
|
||||
const { tool, shouldLockToInitialImage } = canvas;
|
||||
return {
|
||||
tool,
|
||||
isStaging,
|
||||
@ -57,9 +52,8 @@ export const canvasControlsSelector = createSelector(
|
||||
|
||||
const IAICanvasOutpaintingControls = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { tool, isStaging, shouldLockToInitialImage } = useAppSelector(
|
||||
canvasControlsSelector
|
||||
);
|
||||
const { tool, isStaging, shouldLockToInitialImage } =
|
||||
useAppSelector(selector);
|
||||
|
||||
const handleToggleShouldLockToInitialImage = (
|
||||
e: ChangeEvent<HTMLInputElement>
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Spinner } from '@chakra-ui/react';
|
||||
import { useLayoutEffect, useRef } from 'react';
|
||||
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import {
|
||||
baseCanvasImageSelector,
|
||||
currentCanvasSelector,
|
||||
initialCanvasImageSelector,
|
||||
canvasSelector,
|
||||
resizeAndScaleCanvas,
|
||||
resizeCanvas,
|
||||
setCanvasContainerDimensions,
|
||||
@ -13,11 +13,10 @@ import {
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
|
||||
const canvasResizerSelector = createSelector(
|
||||
(state: RootState) => state.canvas,
|
||||
currentCanvasSelector,
|
||||
baseCanvasImageSelector,
|
||||
canvasSelector,
|
||||
initialCanvasImageSelector,
|
||||
activeTabNameSelector,
|
||||
(canvas, currentCanvas, baseCanvasImage, activeTabName) => {
|
||||
(canvas, initialCanvasImage, activeTabName) => {
|
||||
const {
|
||||
doesCanvasNeedScaling,
|
||||
shouldLockToInitialImage,
|
||||
@ -27,7 +26,7 @@ const canvasResizerSelector = createSelector(
|
||||
doesCanvasNeedScaling,
|
||||
shouldLockToInitialImage,
|
||||
activeTabName,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
isCanvasInitialized,
|
||||
};
|
||||
}
|
||||
@ -39,7 +38,7 @@ const IAICanvasResizer = () => {
|
||||
doesCanvasNeedScaling,
|
||||
shouldLockToInitialImage,
|
||||
activeTabName,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
isCanvasInitialized,
|
||||
} = useAppSelector(canvasResizerSelector);
|
||||
|
||||
@ -51,9 +50,10 @@ const IAICanvasResizer = () => {
|
||||
|
||||
const { clientWidth, clientHeight } = ref.current;
|
||||
|
||||
if (!baseCanvasImage?.image) return;
|
||||
if (!initialCanvasImage?.image) return;
|
||||
|
||||
const { width: imageWidth, height: imageHeight } = baseCanvasImage.image;
|
||||
const { width: imageWidth, height: imageHeight } =
|
||||
initialCanvasImage.image;
|
||||
|
||||
dispatch(
|
||||
setCanvasContainerDimensions({
|
||||
@ -70,9 +70,9 @@ const IAICanvasResizer = () => {
|
||||
|
||||
dispatch(setDoesCanvasNeedScaling(false));
|
||||
// }
|
||||
// if ((activeTabName === 'inpainting') && baseCanvasImage?.image) {
|
||||
// if ((activeTabName === 'inpainting') && initialCanvasImage?.image) {
|
||||
// const { width: imageWidth, height: imageHeight } =
|
||||
// baseCanvasImage.image;
|
||||
// initialCanvasImage.image;
|
||||
|
||||
// const scale = Math.min(
|
||||
// 1,
|
||||
@ -100,7 +100,7 @@ const IAICanvasResizer = () => {
|
||||
}, 0);
|
||||
}, [
|
||||
dispatch,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
doesCanvasNeedScaling,
|
||||
activeTabName,
|
||||
isCanvasInitialized,
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
outpaintingCanvasSelector,
|
||||
canvasSelector,
|
||||
setShouldAutoSave,
|
||||
setShouldDarkenOutsideBoundingBox,
|
||||
setShouldShowGrid,
|
||||
@ -17,13 +16,15 @@ import IAIPopover from 'common/components/IAIPopover';
|
||||
import IAICheckbox from 'common/components/IAICheckbox';
|
||||
|
||||
export const canvasControlsSelector = createSelector(
|
||||
[currentCanvasSelector, outpaintingCanvasSelector],
|
||||
(currentCanvas, outpaintingCanvas) => {
|
||||
const { shouldDarkenOutsideBoundingBox, shouldShowIntermediates } =
|
||||
currentCanvas;
|
||||
|
||||
const { shouldShowGrid, shouldSnapToGrid, shouldAutoSave } =
|
||||
outpaintingCanvas;
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const {
|
||||
shouldDarkenOutsideBoundingBox,
|
||||
shouldShowIntermediates,
|
||||
shouldShowGrid,
|
||||
shouldSnapToGrid,
|
||||
shouldAutoSave,
|
||||
} = canvas;
|
||||
|
||||
return {
|
||||
shouldShowGrid,
|
||||
|
@ -1,40 +1,20 @@
|
||||
import { background, ButtonGroup, ChakraProvider } from '@chakra-ui/react';
|
||||
import { CacheProvider } from '@emotion/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { GroupConfig } from 'konva/lib/Group';
|
||||
import _ from 'lodash';
|
||||
import { emotionCache } from 'main';
|
||||
import { useCallback, useState } from 'react';
|
||||
import {
|
||||
FaArrowLeft,
|
||||
FaArrowRight,
|
||||
FaCheck,
|
||||
FaEye,
|
||||
FaEyeSlash,
|
||||
FaTrash,
|
||||
} from 'react-icons/fa';
|
||||
import { Group, Rect } from 'react-konva';
|
||||
import { Html } from 'react-konva-utils';
|
||||
import {
|
||||
commitStagingAreaImage,
|
||||
currentCanvasSelector,
|
||||
discardStagedImages,
|
||||
nextStagingAreaImage,
|
||||
prevStagingAreaImage,
|
||||
} from './canvasSlice';
|
||||
import { canvasSelector } from './canvasSlice';
|
||||
import IAICanvasImage from './IAICanvasImage';
|
||||
|
||||
const selector = createSelector(
|
||||
[currentCanvasSelector],
|
||||
(currentCanvas) => {
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const {
|
||||
layerState: {
|
||||
stagingArea: { images, selectedImageIndex },
|
||||
},
|
||||
} = currentCanvas;
|
||||
} = canvas;
|
||||
|
||||
return {
|
||||
currentStagingAreaImage:
|
||||
@ -54,9 +34,7 @@ type Props = GroupConfig;
|
||||
|
||||
const IAICanvasStagingArea = (props: Props) => {
|
||||
const { ...rest } = props;
|
||||
const dispatch = useAppDispatch();
|
||||
const { isOnFirstImage, isOnLastImage, currentStagingAreaImage } =
|
||||
useAppSelector(selector);
|
||||
const { currentStagingAreaImage } = useAppSelector(selector);
|
||||
|
||||
const [shouldShowStagedImage, setShouldShowStagedImage] =
|
||||
useState<boolean>(true);
|
||||
@ -64,14 +42,6 @@ const IAICanvasStagingArea = (props: Props) => {
|
||||
const [shouldShowStagingAreaOutline, setShouldShowStagingAreaOutline] =
|
||||
useState<boolean>(true);
|
||||
|
||||
const handleMouseOver = useCallback(() => {
|
||||
setShouldShowStagingAreaOutline(false);
|
||||
}, []);
|
||||
|
||||
const handleMouseOut = useCallback(() => {
|
||||
setShouldShowStagingAreaOutline(true);
|
||||
}, []);
|
||||
|
||||
if (!currentStagingAreaImage) return null;
|
||||
|
||||
const {
|
||||
@ -106,73 +76,6 @@ const IAICanvasStagingArea = (props: Props) => {
|
||||
/>
|
||||
</Group>
|
||||
)}
|
||||
{/* <Html>
|
||||
<CacheProvider value={emotionCache}>
|
||||
<ChakraProvider>
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: y + height,
|
||||
left: x + width / 2 - 216 / 2,
|
||||
padding: '0.5rem',
|
||||
filter: 'drop-shadow(0 0.5rem 1rem rgba(0,0,0))',
|
||||
}}
|
||||
>
|
||||
<ButtonGroup isAttached>
|
||||
<IAIIconButton
|
||||
tooltip="Previous"
|
||||
tooltipProps={{ placement: 'bottom' }}
|
||||
aria-label="Previous"
|
||||
icon={<FaArrowLeft />}
|
||||
onClick={() => dispatch(prevStagingAreaImage())}
|
||||
onMouseOver={handleMouseOver}
|
||||
onMouseOut={handleMouseOut}
|
||||
data-selected={true}
|
||||
isDisabled={isOnFirstImage}
|
||||
/>
|
||||
<IAIIconButton
|
||||
tooltip="Next"
|
||||
tooltipProps={{ placement: 'bottom' }}
|
||||
aria-label="Next"
|
||||
icon={<FaArrowRight />}
|
||||
onClick={() => dispatch(nextStagingAreaImage())}
|
||||
onMouseOver={handleMouseOver}
|
||||
onMouseOut={handleMouseOut}
|
||||
data-selected={true}
|
||||
isDisabled={isOnLastImage}
|
||||
/>
|
||||
<IAIIconButton
|
||||
tooltip="Accept"
|
||||
tooltipProps={{ placement: 'bottom' }}
|
||||
aria-label="Accept"
|
||||
icon={<FaCheck />}
|
||||
onClick={() => dispatch(commitStagingAreaImage())}
|
||||
data-selected={true}
|
||||
/>
|
||||
<IAIIconButton
|
||||
tooltip="Show/Hide"
|
||||
tooltipProps={{ placement: 'bottom' }}
|
||||
aria-label="Show/Hide"
|
||||
data-alert={!shouldShowStagedImage}
|
||||
icon={shouldShowStagedImage ? <FaEye /> : <FaEyeSlash />}
|
||||
onClick={() =>
|
||||
setShouldShowStagedImage(!shouldShowStagedImage)
|
||||
}
|
||||
data-selected={true}
|
||||
/>
|
||||
<IAIIconButton
|
||||
tooltip="Discard All"
|
||||
tooltipProps={{ placement: 'bottom' }}
|
||||
aria-label="Discard All"
|
||||
icon={<FaTrash />}
|
||||
onClick={() => dispatch(discardStagedImages())}
|
||||
data-selected={true}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</ChakraProvider>
|
||||
</CacheProvider>
|
||||
</Html> */}
|
||||
</Group>
|
||||
);
|
||||
};
|
||||
|
@ -21,25 +21,22 @@ import {
|
||||
FaEyeSlash,
|
||||
FaTrash,
|
||||
} from 'react-icons/fa';
|
||||
import { Group, Rect } from 'react-konva';
|
||||
import { Html } from 'react-konva-utils';
|
||||
import {
|
||||
commitStagingAreaImage,
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
discardStagedImages,
|
||||
nextStagingAreaImage,
|
||||
prevStagingAreaImage,
|
||||
} from './canvasSlice';
|
||||
import IAICanvasImage from './IAICanvasImage';
|
||||
|
||||
const selector = createSelector(
|
||||
[currentCanvasSelector],
|
||||
(currentCanvas) => {
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const {
|
||||
layerState: {
|
||||
stagingArea: { images, selectedImageIndex },
|
||||
},
|
||||
} = currentCanvas;
|
||||
} = canvas;
|
||||
|
||||
return {
|
||||
currentStagingAreaImage:
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store';
|
||||
import _ from 'lodash';
|
||||
import { currentCanvasSelector } from './canvasSlice';
|
||||
import { canvasSelector } from './canvasSlice';
|
||||
|
||||
const roundToHundreth = (val: number): number => {
|
||||
return Math.round(val * 100) / 100;
|
||||
};
|
||||
|
||||
const selector = createSelector(
|
||||
[currentCanvasSelector],
|
||||
(currentCanvas) => {
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const {
|
||||
stageDimensions: { width: stageWidth, height: stageHeight },
|
||||
stageCoordinates: { x: stageX, y: stageY },
|
||||
@ -17,7 +17,7 @@ const selector = createSelector(
|
||||
boundingBoxCoordinates: { x: boxX, y: boxY },
|
||||
cursorPosition,
|
||||
stageScale,
|
||||
} = currentCanvas;
|
||||
} = canvas;
|
||||
|
||||
const position = cursorPosition
|
||||
? { cursorX: cursorPosition.x, cursorY: cursorPosition.y }
|
||||
|
@ -1,71 +1,11 @@
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
import { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { CanvasState, Dimensions, initialLayerState } from './canvasSlice';
|
||||
import { Vector2d } from 'konva/lib/types';
|
||||
import { CanvasState, initialLayerState } from './canvasSlice';
|
||||
import {
|
||||
roundDownToMultiple,
|
||||
roundToMultiple,
|
||||
} from 'common/util/roundDownToMultiple';
|
||||
import _ from 'lodash';
|
||||
|
||||
// export const setInitialInpaintingImage = (
|
||||
// state: CanvasState,
|
||||
// image: InvokeAI.Image
|
||||
// // action: PayloadAction<InvokeAI.Image>
|
||||
// ) => {
|
||||
// const { width: canvasWidth, height: canvasHeight } =
|
||||
// state.inpainting.stageDimensions;
|
||||
// const { width, height } = state.inpainting.boundingBoxDimensions;
|
||||
// const { x, y } = state.inpainting.boundingBoxCoordinates;
|
||||
|
||||
// const maxWidth = Math.min(image.width, canvasWidth);
|
||||
// const maxHeight = Math.min(image.height, canvasHeight);
|
||||
|
||||
// const newCoordinates: Vector2d = { x, y };
|
||||
// const newDimensions: Dimensions = { width, height };
|
||||
|
||||
// if (width + x > maxWidth) {
|
||||
// // Bounding box at least needs to be translated
|
||||
// if (width > maxWidth) {
|
||||
// // Bounding box also needs to be resized
|
||||
// newDimensions.width = roundDownToMultiple(maxWidth, 64);
|
||||
// }
|
||||
// newCoordinates.x = maxWidth - newDimensions.width;
|
||||
// }
|
||||
|
||||
// if (height + y > maxHeight) {
|
||||
// // Bounding box at least needs to be translated
|
||||
// if (height > maxHeight) {
|
||||
// // Bounding box also needs to be resized
|
||||
// newDimensions.height = roundDownToMultiple(maxHeight, 64);
|
||||
// }
|
||||
// newCoordinates.y = maxHeight - newDimensions.height;
|
||||
// }
|
||||
|
||||
// state.inpainting.boundingBoxDimensions = newDimensions;
|
||||
// state.inpainting.boundingBoxCoordinates = newCoordinates;
|
||||
|
||||
// state.inpainting.pastLayerStates.push(state.inpainting.layerState);
|
||||
|
||||
// state.inpainting.layerState = {
|
||||
// ...initialLayerState,
|
||||
// objects: [
|
||||
// {
|
||||
// kind: 'image',
|
||||
// layer: 'base',
|
||||
// x: 0,
|
||||
// y: 0,
|
||||
// width: image.width,
|
||||
// height: image.height,
|
||||
// image: image,
|
||||
// },
|
||||
// ],
|
||||
// };
|
||||
|
||||
// state.outpainting.futureLayerStates = [];
|
||||
// state.doesCanvasNeedScaling = true;
|
||||
// };
|
||||
|
||||
export const setInitialCanvasImage = (
|
||||
state: CanvasState,
|
||||
image: InvokeAI.Image
|
||||
@ -86,12 +26,12 @@ export const setInitialCanvasImage = (
|
||||
),
|
||||
};
|
||||
|
||||
state.outpainting.boundingBoxDimensions = newBoundingBoxDimensions;
|
||||
state.boundingBoxDimensions = newBoundingBoxDimensions;
|
||||
|
||||
state.outpainting.boundingBoxCoordinates = newBoundingBoxCoordinates;
|
||||
state.boundingBoxCoordinates = newBoundingBoxCoordinates;
|
||||
|
||||
state.outpainting.pastLayerStates.push(state.outpainting.layerState);
|
||||
state.outpainting.layerState = {
|
||||
state.pastLayerStates.push(state.layerState);
|
||||
state.layerState = {
|
||||
...initialLayerState,
|
||||
objects: [
|
||||
{
|
||||
@ -105,7 +45,7 @@ export const setInitialCanvasImage = (
|
||||
},
|
||||
],
|
||||
};
|
||||
state.outpainting.futureLayerStates = [];
|
||||
state.futureLayerStates = [];
|
||||
|
||||
state.isCanvasInitialized = false;
|
||||
state.doesCanvasNeedScaling = true;
|
||||
|
@ -1,10 +1,4 @@
|
||||
import {
|
||||
createAsyncThunk,
|
||||
createSelector,
|
||||
createSlice,
|
||||
current,
|
||||
} from '@reduxjs/toolkit';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { IRect, Vector2d } from 'konva/lib/types';
|
||||
import { RgbaColor } from 'react-colorful';
|
||||
@ -12,10 +6,6 @@ import * as InvokeAI from 'app/invokeai';
|
||||
import _ from 'lodash';
|
||||
import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
|
||||
import { RootState } from 'app/store';
|
||||
import { MutableRefObject } from 'react';
|
||||
import Konva from 'konva';
|
||||
import { tabMap } from 'features/tabs/InvokeTabs';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { mergeAndUploadCanvas } from './util/mergeAndUploadCanvas';
|
||||
import { uploadImage } from 'features/gallery/util/uploadImage';
|
||||
import { setInitialCanvasImage } from './canvasReducers';
|
||||
@ -23,45 +13,6 @@ import calculateScale from './util/calculateScale';
|
||||
import calculateCoordinates from './util/calculateCoordinates';
|
||||
import floorCoordinates from './util/floorCoordinates';
|
||||
|
||||
export interface GenericCanvasState {
|
||||
boundingBoxCoordinates: Vector2d;
|
||||
boundingBoxDimensions: Dimensions;
|
||||
boundingBoxPreviewFill: RgbaColor;
|
||||
brushColor: RgbaColor;
|
||||
brushSize: number;
|
||||
cursorPosition: Vector2d | null;
|
||||
eraserSize: number;
|
||||
futureLayerStates: CanvasLayerState[];
|
||||
inpaintReplace: number;
|
||||
intermediateImage?: InvokeAI.Image;
|
||||
isDrawing: boolean;
|
||||
isMaskEnabled: boolean;
|
||||
isMouseOverBoundingBox: boolean;
|
||||
isMoveBoundingBoxKeyHeld: boolean;
|
||||
isMoveStageKeyHeld: boolean;
|
||||
isMovingBoundingBox: boolean;
|
||||
isMovingStage: boolean;
|
||||
isTransformingBoundingBox: boolean;
|
||||
layerState: CanvasLayerState;
|
||||
maskColor: RgbaColor;
|
||||
maxHistory: number;
|
||||
pastLayerStates: CanvasLayerState[];
|
||||
shouldDarkenOutsideBoundingBox: boolean;
|
||||
shouldLockBoundingBox: boolean;
|
||||
shouldPreserveMaskedArea: boolean;
|
||||
shouldShowBoundingBox: boolean;
|
||||
shouldShowBrush: boolean;
|
||||
shouldShowBrushPreview: boolean;
|
||||
shouldShowCheckboardTransparency: boolean;
|
||||
shouldShowIntermediates: boolean;
|
||||
shouldUseInpaintReplace: boolean;
|
||||
stageCoordinates: Vector2d;
|
||||
stageDimensions: Dimensions;
|
||||
stageScale: number;
|
||||
tool: CanvasTool;
|
||||
minimumStageScale: number;
|
||||
}
|
||||
|
||||
export type CanvasMode = 'inpainting' | 'outpainting';
|
||||
|
||||
export type CanvasLayer = 'base' | 'mask';
|
||||
@ -129,30 +80,51 @@ export const isCanvasAnyLine = (
|
||||
obj: CanvasObject
|
||||
): obj is CanvasMaskLine | CanvasLine => obj.kind === 'line';
|
||||
|
||||
export type OutpaintingCanvasState = GenericCanvasState & {
|
||||
layer: CanvasLayer;
|
||||
shouldShowGrid: boolean;
|
||||
shouldSnapToGrid: boolean;
|
||||
shouldAutoSave: boolean;
|
||||
};
|
||||
|
||||
export type InpaintingCanvasState = GenericCanvasState & {
|
||||
layer: 'mask';
|
||||
};
|
||||
|
||||
export type BaseCanvasState = InpaintingCanvasState | OutpaintingCanvasState;
|
||||
|
||||
export type ValidCanvasName = 'inpainting' | 'outpainting';
|
||||
|
||||
export interface CanvasState {
|
||||
doesCanvasNeedScaling: boolean;
|
||||
currentCanvas: ValidCanvasName;
|
||||
inpainting: InpaintingCanvasState;
|
||||
outpainting: OutpaintingCanvasState;
|
||||
// mode: CanvasMode;
|
||||
shouldLockToInitialImage: boolean;
|
||||
isCanvasInitialized: boolean;
|
||||
boundingBoxCoordinates: Vector2d;
|
||||
boundingBoxDimensions: Dimensions;
|
||||
boundingBoxPreviewFill: RgbaColor;
|
||||
brushColor: RgbaColor;
|
||||
brushSize: number;
|
||||
canvasContainerDimensions: Dimensions;
|
||||
cursorPosition: Vector2d | null;
|
||||
doesCanvasNeedScaling: boolean;
|
||||
eraserSize: number;
|
||||
futureLayerStates: CanvasLayerState[];
|
||||
inpaintReplace: number;
|
||||
intermediateImage?: InvokeAI.Image;
|
||||
isCanvasInitialized: boolean;
|
||||
isDrawing: boolean;
|
||||
isMaskEnabled: boolean;
|
||||
isMouseOverBoundingBox: boolean;
|
||||
isMoveBoundingBoxKeyHeld: boolean;
|
||||
isMoveStageKeyHeld: boolean;
|
||||
isMovingBoundingBox: boolean;
|
||||
isMovingStage: boolean;
|
||||
isTransformingBoundingBox: boolean;
|
||||
layer: CanvasLayer;
|
||||
layerState: CanvasLayerState;
|
||||
maskColor: RgbaColor;
|
||||
maxHistory: number;
|
||||
minimumStageScale: number;
|
||||
pastLayerStates: CanvasLayerState[];
|
||||
shouldAutoSave: boolean;
|
||||
shouldDarkenOutsideBoundingBox: boolean;
|
||||
shouldLockBoundingBox: boolean;
|
||||
shouldLockToInitialImage: boolean;
|
||||
shouldPreserveMaskedArea: boolean;
|
||||
shouldShowBoundingBox: boolean;
|
||||
shouldShowBrush: boolean;
|
||||
shouldShowBrushPreview: boolean;
|
||||
shouldShowCheckboardTransparency: boolean;
|
||||
shouldShowGrid: boolean;
|
||||
shouldShowIntermediates: boolean;
|
||||
shouldSnapToGrid: boolean;
|
||||
shouldUseInpaintReplace: boolean;
|
||||
stageCoordinates: Vector2d;
|
||||
stageDimensions: Dimensions;
|
||||
stageScale: number;
|
||||
tool: CanvasTool;
|
||||
}
|
||||
|
||||
export const initialLayerState: CanvasLayerState = {
|
||||
@ -167,16 +139,19 @@ export const initialLayerState: CanvasLayerState = {
|
||||
},
|
||||
};
|
||||
|
||||
const initialGenericCanvasState: GenericCanvasState = {
|
||||
const initialCanvasState: CanvasState = {
|
||||
boundingBoxCoordinates: { x: 0, y: 0 },
|
||||
boundingBoxDimensions: { width: 512, height: 512 },
|
||||
boundingBoxPreviewFill: { r: 0, g: 0, b: 0, a: 0.5 },
|
||||
brushColor: { r: 90, g: 90, b: 255, a: 1 },
|
||||
brushSize: 50,
|
||||
canvasContainerDimensions: { width: 0, height: 0 },
|
||||
cursorPosition: null,
|
||||
doesCanvasNeedScaling: false,
|
||||
eraserSize: 50,
|
||||
futureLayerStates: [],
|
||||
inpaintReplace: 0.1,
|
||||
isCanvasInitialized: false,
|
||||
isDrawing: false,
|
||||
isMaskEnabled: true,
|
||||
isMouseOverBoundingBox: false,
|
||||
@ -185,121 +160,101 @@ const initialGenericCanvasState: GenericCanvasState = {
|
||||
isMovingBoundingBox: false,
|
||||
isMovingStage: false,
|
||||
isTransformingBoundingBox: false,
|
||||
layer: 'base',
|
||||
layerState: initialLayerState,
|
||||
maskColor: { r: 255, g: 90, b: 90, a: 1 },
|
||||
maxHistory: 128,
|
||||
minimumStageScale: 1,
|
||||
pastLayerStates: [],
|
||||
shouldAutoSave: false,
|
||||
shouldDarkenOutsideBoundingBox: false,
|
||||
shouldLockBoundingBox: false,
|
||||
shouldLockToInitialImage: false,
|
||||
shouldPreserveMaskedArea: false,
|
||||
shouldShowBoundingBox: true,
|
||||
shouldShowBrush: true,
|
||||
shouldShowBrushPreview: false,
|
||||
shouldShowCheckboardTransparency: false,
|
||||
shouldShowGrid: true,
|
||||
shouldShowIntermediates: true,
|
||||
shouldSnapToGrid: true,
|
||||
shouldUseInpaintReplace: false,
|
||||
stageCoordinates: { x: 0, y: 0 },
|
||||
stageDimensions: { width: 0, height: 0 },
|
||||
stageScale: 1,
|
||||
minimumStageScale: 1,
|
||||
tool: 'brush',
|
||||
};
|
||||
|
||||
const initialCanvasState: CanvasState = {
|
||||
currentCanvas: 'inpainting',
|
||||
doesCanvasNeedScaling: false,
|
||||
shouldLockToInitialImage: false,
|
||||
// mode: 'outpainting',
|
||||
isCanvasInitialized: false,
|
||||
canvasContainerDimensions: { width: 0, height: 0 },
|
||||
inpainting: {
|
||||
layer: 'mask',
|
||||
...initialGenericCanvasState,
|
||||
},
|
||||
outpainting: {
|
||||
layer: 'base',
|
||||
shouldShowGrid: true,
|
||||
shouldSnapToGrid: true,
|
||||
shouldAutoSave: false,
|
||||
...initialGenericCanvasState,
|
||||
},
|
||||
};
|
||||
|
||||
export const canvasSlice = createSlice({
|
||||
name: 'canvas',
|
||||
initialState: initialCanvasState,
|
||||
reducers: {
|
||||
setTool: (state, action: PayloadAction<CanvasTool>) => {
|
||||
const tool = action.payload;
|
||||
state[state.currentCanvas].tool = action.payload;
|
||||
state.tool = action.payload;
|
||||
if (tool !== 'move') {
|
||||
state[state.currentCanvas].isTransformingBoundingBox = false;
|
||||
state[state.currentCanvas].isMouseOverBoundingBox = false;
|
||||
state[state.currentCanvas].isMovingBoundingBox = false;
|
||||
state[state.currentCanvas].isMovingStage = false;
|
||||
state.isTransformingBoundingBox = false;
|
||||
state.isMouseOverBoundingBox = false;
|
||||
state.isMovingBoundingBox = false;
|
||||
state.isMovingStage = false;
|
||||
}
|
||||
},
|
||||
setLayer: (state, action: PayloadAction<CanvasLayer>) => {
|
||||
state[state.currentCanvas].layer = action.payload;
|
||||
state.layer = action.payload;
|
||||
},
|
||||
toggleTool: (state) => {
|
||||
const currentTool = state[state.currentCanvas].tool;
|
||||
const currentTool = state.tool;
|
||||
if (currentTool !== 'move') {
|
||||
state[state.currentCanvas].tool =
|
||||
currentTool === 'brush' ? 'eraser' : 'brush';
|
||||
state.tool = currentTool === 'brush' ? 'eraser' : 'brush';
|
||||
}
|
||||
},
|
||||
setMaskColor: (state, action: PayloadAction<RgbaColor>) => {
|
||||
state[state.currentCanvas].maskColor = action.payload;
|
||||
state.maskColor = action.payload;
|
||||
},
|
||||
setBrushColor: (state, action: PayloadAction<RgbaColor>) => {
|
||||
state[state.currentCanvas].brushColor = action.payload;
|
||||
state.brushColor = action.payload;
|
||||
},
|
||||
setBrushSize: (state, action: PayloadAction<number>) => {
|
||||
state[state.currentCanvas].brushSize = action.payload;
|
||||
state.brushSize = action.payload;
|
||||
},
|
||||
setEraserSize: (state, action: PayloadAction<number>) => {
|
||||
state[state.currentCanvas].eraserSize = action.payload;
|
||||
state.eraserSize = action.payload;
|
||||
},
|
||||
clearMask: (state) => {
|
||||
const currentCanvas = state[state.currentCanvas];
|
||||
currentCanvas.pastLayerStates.push(currentCanvas.layerState);
|
||||
currentCanvas.layerState.objects = state[
|
||||
state.currentCanvas
|
||||
].layerState.objects.filter((obj) => !isCanvasMaskLine(obj));
|
||||
currentCanvas.futureLayerStates = [];
|
||||
currentCanvas.shouldPreserveMaskedArea = false;
|
||||
state.pastLayerStates.push(state.layerState);
|
||||
state.layerState.objects = state.layerState.objects.filter(
|
||||
(obj) => !isCanvasMaskLine(obj)
|
||||
);
|
||||
state.futureLayerStates = [];
|
||||
state.shouldPreserveMaskedArea = false;
|
||||
},
|
||||
toggleShouldInvertMask: (state) => {
|
||||
state[state.currentCanvas].shouldPreserveMaskedArea =
|
||||
!state[state.currentCanvas].shouldPreserveMaskedArea;
|
||||
state.shouldPreserveMaskedArea = !state.shouldPreserveMaskedArea;
|
||||
},
|
||||
toggleShouldShowMask: (state) => {
|
||||
state[state.currentCanvas].isMaskEnabled =
|
||||
!state[state.currentCanvas].isMaskEnabled;
|
||||
state.isMaskEnabled = !state.isMaskEnabled;
|
||||
},
|
||||
setShouldPreserveMaskedArea: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].shouldPreserveMaskedArea = action.payload;
|
||||
state.shouldPreserveMaskedArea = action.payload;
|
||||
},
|
||||
setIsMaskEnabled: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].isMaskEnabled = action.payload;
|
||||
state[state.currentCanvas].layer = action.payload ? 'mask' : 'base';
|
||||
state.isMaskEnabled = action.payload;
|
||||
state.layer = action.payload ? 'mask' : 'base';
|
||||
},
|
||||
setShouldShowCheckboardTransparency: (
|
||||
state,
|
||||
action: PayloadAction<boolean>
|
||||
) => {
|
||||
state[state.currentCanvas].shouldShowCheckboardTransparency =
|
||||
action.payload;
|
||||
state.shouldShowCheckboardTransparency = action.payload;
|
||||
},
|
||||
setShouldShowBrushPreview: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].shouldShowBrushPreview = action.payload;
|
||||
state.shouldShowBrushPreview = action.payload;
|
||||
},
|
||||
setShouldShowBrush: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].shouldShowBrush = action.payload;
|
||||
state.shouldShowBrush = action.payload;
|
||||
},
|
||||
setCursorPosition: (state, action: PayloadAction<Vector2d | null>) => {
|
||||
state[state.currentCanvas].cursorPosition = action.payload;
|
||||
state.cursorPosition = action.payload;
|
||||
},
|
||||
clearImageToInpaint: (state) => {
|
||||
// TODO
|
||||
@ -312,102 +267,87 @@ export const canvasSlice = createSlice({
|
||||
setInitialCanvasImage(state, action.payload);
|
||||
},
|
||||
setStageDimensions: (state, action: PayloadAction<Dimensions>) => {
|
||||
state[state.currentCanvas].stageDimensions = action.payload;
|
||||
state.stageDimensions = action.payload;
|
||||
|
||||
const { width: canvasWidth, height: canvasHeight } = action.payload;
|
||||
|
||||
const { width: boundingBoxWidth, height: boundingBoxHeight } =
|
||||
state[state.currentCanvas].boundingBoxDimensions;
|
||||
state.boundingBoxDimensions;
|
||||
|
||||
const newBoundingBoxWidth = roundDownToMultiple(
|
||||
_.clamp(
|
||||
boundingBoxWidth,
|
||||
64,
|
||||
canvasWidth / state[state.currentCanvas].stageScale
|
||||
),
|
||||
_.clamp(boundingBoxWidth, 64, canvasWidth / state.stageScale),
|
||||
64
|
||||
);
|
||||
const newBoundingBoxHeight = roundDownToMultiple(
|
||||
_.clamp(
|
||||
boundingBoxHeight,
|
||||
64,
|
||||
canvasHeight / state[state.currentCanvas].stageScale
|
||||
),
|
||||
_.clamp(boundingBoxHeight, 64, canvasHeight / state.stageScale),
|
||||
64
|
||||
);
|
||||
|
||||
state[state.currentCanvas].boundingBoxDimensions = {
|
||||
state.boundingBoxDimensions = {
|
||||
width: newBoundingBoxWidth,
|
||||
height: newBoundingBoxHeight,
|
||||
};
|
||||
},
|
||||
setBoundingBoxDimensions: (state, action: PayloadAction<Dimensions>) => {
|
||||
state[state.currentCanvas].boundingBoxDimensions = action.payload;
|
||||
state.boundingBoxDimensions = action.payload;
|
||||
},
|
||||
setBoundingBoxCoordinates: (state, action: PayloadAction<Vector2d>) => {
|
||||
state[state.currentCanvas].boundingBoxCoordinates = floorCoordinates(
|
||||
action.payload
|
||||
);
|
||||
state.boundingBoxCoordinates = floorCoordinates(action.payload);
|
||||
},
|
||||
setStageCoordinates: (state, action: PayloadAction<Vector2d>) => {
|
||||
state.outpainting.stageCoordinates = floorCoordinates(action.payload);
|
||||
state.stageCoordinates = floorCoordinates(action.payload);
|
||||
},
|
||||
setBoundingBoxPreviewFill: (state, action: PayloadAction<RgbaColor>) => {
|
||||
state[state.currentCanvas].boundingBoxPreviewFill = action.payload;
|
||||
state.boundingBoxPreviewFill = action.payload;
|
||||
},
|
||||
setDoesCanvasNeedScaling: (state, action: PayloadAction<boolean>) => {
|
||||
state.doesCanvasNeedScaling = action.payload;
|
||||
},
|
||||
setStageScale: (state, action: PayloadAction<number>) => {
|
||||
state[state.currentCanvas].stageScale = action.payload;
|
||||
state.stageScale = action.payload;
|
||||
},
|
||||
setShouldDarkenOutsideBoundingBox: (
|
||||
state,
|
||||
action: PayloadAction<boolean>
|
||||
) => {
|
||||
state[state.currentCanvas].shouldDarkenOutsideBoundingBox =
|
||||
action.payload;
|
||||
state.shouldDarkenOutsideBoundingBox = action.payload;
|
||||
},
|
||||
setIsDrawing: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].isDrawing = action.payload;
|
||||
state.isDrawing = action.payload;
|
||||
},
|
||||
setClearBrushHistory: (state) => {
|
||||
state[state.currentCanvas].pastLayerStates = [];
|
||||
state[state.currentCanvas].futureLayerStates = [];
|
||||
state.pastLayerStates = [];
|
||||
state.futureLayerStates = [];
|
||||
},
|
||||
setShouldUseInpaintReplace: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].shouldUseInpaintReplace = action.payload;
|
||||
state.shouldUseInpaintReplace = action.payload;
|
||||
},
|
||||
setInpaintReplace: (state, action: PayloadAction<number>) => {
|
||||
state[state.currentCanvas].inpaintReplace = action.payload;
|
||||
state.inpaintReplace = action.payload;
|
||||
},
|
||||
setShouldLockBoundingBox: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].shouldLockBoundingBox = action.payload;
|
||||
state.shouldLockBoundingBox = action.payload;
|
||||
},
|
||||
toggleShouldLockBoundingBox: (state) => {
|
||||
state[state.currentCanvas].shouldLockBoundingBox =
|
||||
!state[state.currentCanvas].shouldLockBoundingBox;
|
||||
state.shouldLockBoundingBox = !state.shouldLockBoundingBox;
|
||||
},
|
||||
setShouldShowBoundingBox: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].shouldShowBoundingBox = action.payload;
|
||||
state.shouldShowBoundingBox = action.payload;
|
||||
},
|
||||
setIsTransformingBoundingBox: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].isTransformingBoundingBox = action.payload;
|
||||
state.isTransformingBoundingBox = action.payload;
|
||||
},
|
||||
setIsMovingBoundingBox: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].isMovingBoundingBox = action.payload;
|
||||
state.isMovingBoundingBox = action.payload;
|
||||
},
|
||||
setIsMouseOverBoundingBox: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].isMouseOverBoundingBox = action.payload;
|
||||
state.isMouseOverBoundingBox = action.payload;
|
||||
},
|
||||
setIsMoveBoundingBoxKeyHeld: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].isMoveBoundingBoxKeyHeld = action.payload;
|
||||
state.isMoveBoundingBoxKeyHeld = action.payload;
|
||||
},
|
||||
setIsMoveStageKeyHeld: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].isMoveStageKeyHeld = action.payload;
|
||||
},
|
||||
setCurrentCanvas: (state, action: PayloadAction<ValidCanvasName>) => {
|
||||
state.currentCanvas = action.payload;
|
||||
state.isMoveStageKeyHeld = action.payload;
|
||||
},
|
||||
addImageToStagingArea: (
|
||||
state,
|
||||
@ -420,36 +360,31 @@ export const canvasSlice = createSlice({
|
||||
|
||||
if (!boundingBox || !image) return;
|
||||
|
||||
const currentCanvas = state.outpainting;
|
||||
state.pastLayerStates.push(_.cloneDeep(state.layerState));
|
||||
|
||||
currentCanvas.pastLayerStates.push(_.cloneDeep(currentCanvas.layerState));
|
||||
|
||||
if (currentCanvas.pastLayerStates.length > currentCanvas.maxHistory) {
|
||||
currentCanvas.pastLayerStates.shift();
|
||||
if (state.pastLayerStates.length > state.maxHistory) {
|
||||
state.pastLayerStates.shift();
|
||||
}
|
||||
|
||||
currentCanvas.layerState.stagingArea.images.push({
|
||||
state.layerState.stagingArea.images.push({
|
||||
kind: 'image',
|
||||
layer: 'base',
|
||||
...boundingBox,
|
||||
image,
|
||||
});
|
||||
|
||||
currentCanvas.layerState.stagingArea.selectedImageIndex =
|
||||
currentCanvas.layerState.stagingArea.images.length - 1;
|
||||
state.layerState.stagingArea.selectedImageIndex =
|
||||
state.layerState.stagingArea.images.length - 1;
|
||||
|
||||
currentCanvas.futureLayerStates = [];
|
||||
state.futureLayerStates = [];
|
||||
},
|
||||
discardStagedImages: (state) => {
|
||||
const currentCanvas = state[state.currentCanvas];
|
||||
currentCanvas.layerState.stagingArea = {
|
||||
state.layerState.stagingArea = {
|
||||
...initialLayerState.stagingArea,
|
||||
};
|
||||
},
|
||||
addLine: (state, action: PayloadAction<number[]>) => {
|
||||
const currentCanvas = state[state.currentCanvas];
|
||||
|
||||
const { tool, layer, brushColor, brushSize, eraserSize } = currentCanvas;
|
||||
const { tool, layer, brushColor, brushSize, eraserSize } = state;
|
||||
|
||||
if (tool === 'move') return;
|
||||
|
||||
@ -459,13 +394,13 @@ export const canvasSlice = createSlice({
|
||||
const newColor =
|
||||
layer === 'base' && tool === 'brush' ? { color: brushColor } : {};
|
||||
|
||||
currentCanvas.pastLayerStates.push(currentCanvas.layerState);
|
||||
state.pastLayerStates.push(state.layerState);
|
||||
|
||||
if (currentCanvas.pastLayerStates.length > currentCanvas.maxHistory) {
|
||||
currentCanvas.pastLayerStates.shift();
|
||||
if (state.pastLayerStates.length > state.maxHistory) {
|
||||
state.pastLayerStates.shift();
|
||||
}
|
||||
|
||||
currentCanvas.layerState.objects.push({
|
||||
state.layerState.objects.push({
|
||||
kind: 'line',
|
||||
layer,
|
||||
tool,
|
||||
@ -474,68 +409,61 @@ export const canvasSlice = createSlice({
|
||||
...newColor,
|
||||
});
|
||||
|
||||
currentCanvas.futureLayerStates = [];
|
||||
state.futureLayerStates = [];
|
||||
},
|
||||
addPointToCurrentLine: (state, action: PayloadAction<number[]>) => {
|
||||
const lastLine =
|
||||
state[state.currentCanvas].layerState.objects.findLast(isCanvasAnyLine);
|
||||
const lastLine = state.layerState.objects.findLast(isCanvasAnyLine);
|
||||
|
||||
if (!lastLine) return;
|
||||
|
||||
lastLine.points.push(...action.payload);
|
||||
},
|
||||
undo: (state) => {
|
||||
const currentCanvas = state[state.currentCanvas];
|
||||
|
||||
const targetState = currentCanvas.pastLayerStates.pop();
|
||||
const targetState = state.pastLayerStates.pop();
|
||||
|
||||
if (!targetState) return;
|
||||
|
||||
currentCanvas.futureLayerStates.unshift(currentCanvas.layerState);
|
||||
state.futureLayerStates.unshift(state.layerState);
|
||||
|
||||
if (currentCanvas.futureLayerStates.length > currentCanvas.maxHistory) {
|
||||
currentCanvas.futureLayerStates.pop();
|
||||
if (state.futureLayerStates.length > state.maxHistory) {
|
||||
state.futureLayerStates.pop();
|
||||
}
|
||||
|
||||
currentCanvas.layerState = targetState;
|
||||
state.layerState = targetState;
|
||||
},
|
||||
redo: (state) => {
|
||||
const currentCanvas = state[state.currentCanvas];
|
||||
|
||||
const targetState = currentCanvas.futureLayerStates.shift();
|
||||
const targetState = state.futureLayerStates.shift();
|
||||
|
||||
if (!targetState) return;
|
||||
|
||||
currentCanvas.pastLayerStates.push(currentCanvas.layerState);
|
||||
state.pastLayerStates.push(state.layerState);
|
||||
|
||||
if (currentCanvas.pastLayerStates.length > currentCanvas.maxHistory) {
|
||||
currentCanvas.pastLayerStates.shift();
|
||||
if (state.pastLayerStates.length > state.maxHistory) {
|
||||
state.pastLayerStates.shift();
|
||||
}
|
||||
|
||||
currentCanvas.layerState = targetState;
|
||||
state.layerState = targetState;
|
||||
},
|
||||
setShouldShowGrid: (state, action: PayloadAction<boolean>) => {
|
||||
state.outpainting.shouldShowGrid = action.payload;
|
||||
state.shouldShowGrid = action.payload;
|
||||
},
|
||||
setIsMovingStage: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].isMovingStage = action.payload;
|
||||
state.isMovingStage = action.payload;
|
||||
},
|
||||
setShouldSnapToGrid: (state, action: PayloadAction<boolean>) => {
|
||||
state.outpainting.shouldSnapToGrid = action.payload;
|
||||
state.shouldSnapToGrid = action.payload;
|
||||
},
|
||||
setShouldAutoSave: (state, action: PayloadAction<boolean>) => {
|
||||
state.outpainting.shouldAutoSave = action.payload;
|
||||
state.shouldAutoSave = action.payload;
|
||||
},
|
||||
setShouldShowIntermediates: (state, action: PayloadAction<boolean>) => {
|
||||
state[state.currentCanvas].shouldShowIntermediates = action.payload;
|
||||
state.shouldShowIntermediates = action.payload;
|
||||
},
|
||||
resetCanvas: (state) => {
|
||||
state[state.currentCanvas].pastLayerStates.push(
|
||||
state[state.currentCanvas].layerState
|
||||
);
|
||||
state.pastLayerStates.push(state.layerState);
|
||||
|
||||
state[state.currentCanvas].layerState = initialLayerState;
|
||||
state[state.currentCanvas].futureLayerStates = [];
|
||||
state.layerState = initialLayerState;
|
||||
state.futureLayerStates = [];
|
||||
},
|
||||
setCanvasContainerDimensions: (
|
||||
state,
|
||||
@ -548,7 +476,7 @@ export const canvasSlice = createSlice({
|
||||
state.canvasContainerDimensions;
|
||||
|
||||
const initialCanvasImage =
|
||||
state.outpainting.layerState.objects.find(isCanvasBaseImage);
|
||||
state.layerState.objects.find(isCanvasBaseImage);
|
||||
|
||||
if (!initialCanvasImage) return;
|
||||
|
||||
@ -559,8 +487,6 @@ export const canvasSlice = createSlice({
|
||||
|
||||
const { shouldLockToInitialImage } = state;
|
||||
|
||||
const currentCanvas = state[state.currentCanvas];
|
||||
|
||||
const padding = shouldLockToInitialImage ? 1 : 0.95;
|
||||
|
||||
const newScale = calculateScale(
|
||||
@ -590,20 +516,18 @@ export const canvasSlice = createSlice({
|
||||
newScale
|
||||
);
|
||||
|
||||
currentCanvas.stageScale = newScale;
|
||||
currentCanvas.minimumStageScale = newScale;
|
||||
currentCanvas.stageCoordinates = newCoordinates;
|
||||
state.stageScale = newScale;
|
||||
state.minimumStageScale = newScale;
|
||||
state.stageCoordinates = newCoordinates;
|
||||
|
||||
currentCanvas.stageDimensions = newDimensions;
|
||||
state.stageDimensions = newDimensions;
|
||||
state.isCanvasInitialized = true;
|
||||
},
|
||||
resizeCanvas: (state) => {
|
||||
const { width: containerWidth, height: containerHeight } =
|
||||
state.canvasContainerDimensions;
|
||||
|
||||
const currentCanvas = state[state.currentCanvas];
|
||||
|
||||
currentCanvas.stageDimensions = {
|
||||
state.stageDimensions = {
|
||||
width: Math.floor(containerWidth),
|
||||
height: Math.floor(containerHeight),
|
||||
};
|
||||
@ -616,16 +540,13 @@ export const canvasSlice = createSlice({
|
||||
) => {
|
||||
const { contentRect } = action.payload;
|
||||
|
||||
const currentCanvas = state[state.currentCanvas];
|
||||
|
||||
const baseCanvasImage =
|
||||
currentCanvas.layerState.objects.find(isCanvasBaseImage);
|
||||
const baseCanvasImage = state.layerState.objects.find(isCanvasBaseImage);
|
||||
const { shouldLockToInitialImage } = state;
|
||||
if (!baseCanvasImage) return;
|
||||
|
||||
const {
|
||||
stageDimensions: { width: stageWidth, height: stageHeight },
|
||||
} = currentCanvas;
|
||||
} = state;
|
||||
|
||||
const { x, y, width, height } = contentRect;
|
||||
|
||||
@ -648,56 +569,49 @@ export const canvasSlice = createSlice({
|
||||
newScale
|
||||
);
|
||||
|
||||
currentCanvas.stageScale = newScale;
|
||||
state.stageScale = newScale;
|
||||
|
||||
currentCanvas.stageCoordinates = newCoordinates;
|
||||
state.stageCoordinates = newCoordinates;
|
||||
},
|
||||
nextStagingAreaImage: (state) => {
|
||||
const currentIndex =
|
||||
state.outpainting.layerState.stagingArea.selectedImageIndex;
|
||||
const length = state.outpainting.layerState.stagingArea.images.length;
|
||||
const currentIndex = state.layerState.stagingArea.selectedImageIndex;
|
||||
const length = state.layerState.stagingArea.images.length;
|
||||
|
||||
state.outpainting.layerState.stagingArea.selectedImageIndex = Math.min(
|
||||
state.layerState.stagingArea.selectedImageIndex = Math.min(
|
||||
currentIndex + 1,
|
||||
length - 1
|
||||
);
|
||||
},
|
||||
prevStagingAreaImage: (state) => {
|
||||
const currentIndex =
|
||||
state.outpainting.layerState.stagingArea.selectedImageIndex;
|
||||
const currentIndex = state.layerState.stagingArea.selectedImageIndex;
|
||||
|
||||
state.outpainting.layerState.stagingArea.selectedImageIndex = Math.max(
|
||||
state.layerState.stagingArea.selectedImageIndex = Math.max(
|
||||
currentIndex - 1,
|
||||
0
|
||||
);
|
||||
},
|
||||
commitStagingAreaImage: (state) => {
|
||||
const currentCanvas = state[state.currentCanvas];
|
||||
const { images, selectedImageIndex } =
|
||||
currentCanvas.layerState.stagingArea;
|
||||
const { images, selectedImageIndex } = state.layerState.stagingArea;
|
||||
|
||||
currentCanvas.pastLayerStates.push(_.cloneDeep(currentCanvas.layerState));
|
||||
state.pastLayerStates.push(_.cloneDeep(state.layerState));
|
||||
|
||||
if (currentCanvas.pastLayerStates.length > currentCanvas.maxHistory) {
|
||||
currentCanvas.pastLayerStates.shift();
|
||||
if (state.pastLayerStates.length > state.maxHistory) {
|
||||
state.pastLayerStates.shift();
|
||||
}
|
||||
|
||||
currentCanvas.layerState.objects.push({
|
||||
state.layerState.objects.push({
|
||||
...images[selectedImageIndex],
|
||||
});
|
||||
|
||||
currentCanvas.layerState.stagingArea = {
|
||||
state.layerState.stagingArea = {
|
||||
...initialLayerState.stagingArea,
|
||||
};
|
||||
|
||||
currentCanvas.futureLayerStates = [];
|
||||
state.futureLayerStates = [];
|
||||
},
|
||||
setShouldLockToInitialImage: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldLockToInitialImage = action.payload;
|
||||
},
|
||||
// setCanvasMode: (state, action: PayloadAction<CanvasMode>) => {
|
||||
// state.mode = action.payload;
|
||||
// },
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(mergeAndUploadCanvas.fulfilled, (state, action) => {
|
||||
@ -705,13 +619,13 @@ export const canvasSlice = createSlice({
|
||||
const { image, kind, originalBoundingBox } = action.payload;
|
||||
|
||||
if (kind === 'temp_merged_canvas') {
|
||||
state.outpainting.pastLayerStates.push({
|
||||
...state.outpainting.layerState,
|
||||
state.pastLayerStates.push({
|
||||
...state.layerState,
|
||||
});
|
||||
|
||||
state.outpainting.futureLayerStates = [];
|
||||
state.futureLayerStates = [];
|
||||
|
||||
state.outpainting.layerState.objects = [
|
||||
state.layerState.objects = [
|
||||
{
|
||||
kind: 'image',
|
||||
layer: 'base',
|
||||
@ -779,7 +693,6 @@ export const {
|
||||
setIsMoveBoundingBoxKeyHeld,
|
||||
setIsMoveStageKeyHeld,
|
||||
setStageCoordinates,
|
||||
setCurrentCanvas,
|
||||
addImageToStagingArea,
|
||||
resetCanvas,
|
||||
setShouldShowGrid,
|
||||
@ -800,41 +713,15 @@ export const {
|
||||
|
||||
export default canvasSlice.reducer;
|
||||
|
||||
export const currentCanvasSelector = (state: RootState): BaseCanvasState =>
|
||||
state.canvas[state.canvas.currentCanvas];
|
||||
export const canvasSelector = (state: RootState): CanvasState => state.canvas;
|
||||
|
||||
export const isStagingSelector = (state: RootState): boolean =>
|
||||
state.canvas[state.canvas.currentCanvas].layerState.stagingArea.images
|
||||
.length > 0;
|
||||
|
||||
export const outpaintingCanvasSelector = (
|
||||
state: RootState
|
||||
): OutpaintingCanvasState => state.canvas.outpainting;
|
||||
|
||||
export const inpaintingCanvasSelector = (
|
||||
state: RootState
|
||||
): InpaintingCanvasState => state.canvas.inpainting;
|
||||
state.canvas.layerState.stagingArea.images.length > 0;
|
||||
|
||||
export const shouldLockToInitialImageSelector = (state: RootState): boolean =>
|
||||
state.canvas.shouldLockToInitialImage;
|
||||
|
||||
export const baseCanvasImageSelector = createSelector(
|
||||
[currentCanvasSelector],
|
||||
(currentCanvas) => {
|
||||
return currentCanvas.layerState.objects.find(isCanvasBaseImage);
|
||||
}
|
||||
);
|
||||
|
||||
// export const canvasClipSelector = createSelector(
|
||||
// [canvasModeSelector, baseCanvasImageSelector],
|
||||
// (canvasMode, baseCanvasImage) => {
|
||||
// return canvasMode === 'inpainting'
|
||||
// ? {
|
||||
// clipX: 0,
|
||||
// clipY: 0,
|
||||
// clipWidth: baseCanvasImage?.width,
|
||||
// clipHeight: baseCanvasImage?.height,
|
||||
// }
|
||||
// : {};
|
||||
// }
|
||||
// );
|
||||
export const initialCanvasImageSelector = (
|
||||
state: RootState
|
||||
): CanvasImage | undefined =>
|
||||
state.canvas.layerState.objects.find(isCanvasBaseImage);
|
||||
|
@ -1,20 +1,17 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import _ from 'lodash';
|
||||
import { useCallback } from 'react';
|
||||
import {
|
||||
baseCanvasImageSelector,
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
setIsMovingStage,
|
||||
setStageCoordinates,
|
||||
shouldLockToInitialImageSelector,
|
||||
} from '../canvasSlice';
|
||||
|
||||
const selector = createSelector(
|
||||
[currentCanvasSelector, isStagingSelector],
|
||||
[canvasSelector, isStagingSelector],
|
||||
(canvas, isStaging) => {
|
||||
const { tool } = canvas;
|
||||
return {
|
||||
|
@ -9,19 +9,19 @@ import {
|
||||
toggleShouldLockBoundingBox,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { currentCanvasSelector } from '../canvasSlice';
|
||||
import { canvasSelector } from '../canvasSlice';
|
||||
import { useRef } from 'react';
|
||||
import { stageRef } from '../IAICanvas';
|
||||
|
||||
const inpaintingCanvasHotkeysSelector = createSelector(
|
||||
[currentCanvasSelector, activeTabNameSelector],
|
||||
(currentCanvas, activeTabName) => {
|
||||
[canvasSelector, activeTabNameSelector],
|
||||
(canvas, activeTabName) => {
|
||||
const {
|
||||
cursorPosition,
|
||||
shouldLockBoundingBox,
|
||||
shouldShowBoundingBox,
|
||||
tool,
|
||||
} = currentCanvas;
|
||||
} = canvas;
|
||||
|
||||
return {
|
||||
activeTabName,
|
||||
|
@ -7,7 +7,7 @@ import _ from 'lodash';
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
import {
|
||||
addLine,
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
setIsDrawing,
|
||||
setIsMovingStage,
|
||||
@ -15,9 +15,9 @@ import {
|
||||
import getScaledCursorPosition from '../util/getScaledCursorPosition';
|
||||
|
||||
const selector = createSelector(
|
||||
[activeTabNameSelector, currentCanvasSelector, isStagingSelector],
|
||||
(activeTabName, currentCanvas, isStaging) => {
|
||||
const { tool } = currentCanvas;
|
||||
[activeTabNameSelector, canvasSelector, isStagingSelector],
|
||||
(activeTabName, canvas, isStaging) => {
|
||||
const { tool } = canvas;
|
||||
return {
|
||||
tool,
|
||||
activeTabName,
|
||||
|
@ -7,16 +7,16 @@ import _ from 'lodash';
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
import {
|
||||
addLine,
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
setIsDrawing,
|
||||
} from '../canvasSlice';
|
||||
import getScaledCursorPosition from '../util/getScaledCursorPosition';
|
||||
|
||||
const selector = createSelector(
|
||||
[activeTabNameSelector, currentCanvasSelector, isStagingSelector],
|
||||
(activeTabName, currentCanvas, isStaging) => {
|
||||
const { tool } = currentCanvas;
|
||||
[activeTabNameSelector, canvasSelector, isStagingSelector],
|
||||
(activeTabName, canvas, isStaging) => {
|
||||
const { tool } = canvas;
|
||||
return {
|
||||
tool,
|
||||
activeTabName,
|
||||
|
@ -7,17 +7,16 @@ import _ from 'lodash';
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
import {
|
||||
addPointToCurrentLine,
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
setCursorPosition,
|
||||
} from '../canvasSlice';
|
||||
import getScaledCursorPosition from '../util/getScaledCursorPosition';
|
||||
|
||||
const selector = createSelector(
|
||||
[activeTabNameSelector, currentCanvasSelector, isStagingSelector],
|
||||
(activeTabName, currentCanvas, isStaging) => {
|
||||
const { tool, isDrawing } = currentCanvas;
|
||||
[activeTabNameSelector, canvasSelector, isStagingSelector],
|
||||
(activeTabName, canvas, isStaging) => {
|
||||
const { tool, isDrawing } = canvas;
|
||||
return {
|
||||
tool,
|
||||
isDrawing,
|
||||
|
@ -7,8 +7,7 @@ import { MutableRefObject, useCallback } from 'react';
|
||||
import {
|
||||
// addPointToCurrentEraserLine,
|
||||
addPointToCurrentLine,
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
setIsDrawing,
|
||||
setIsMovingStage,
|
||||
@ -16,9 +15,9 @@ import {
|
||||
import getScaledCursorPosition from '../util/getScaledCursorPosition';
|
||||
|
||||
const selector = createSelector(
|
||||
[activeTabNameSelector, currentCanvasSelector, isStagingSelector],
|
||||
(activeTabName, currentCanvas, isStaging) => {
|
||||
const { tool, isDrawing } = currentCanvas;
|
||||
[activeTabNameSelector, canvasSelector, isStagingSelector],
|
||||
(activeTabName, canvas, isStaging) => {
|
||||
const { tool, isDrawing } = canvas;
|
||||
return {
|
||||
tool,
|
||||
isDrawing,
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { activeTabNameSelector } from 'features/options/optionsSelectors';
|
||||
import Konva from 'konva';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import _ from 'lodash';
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
import {
|
||||
baseCanvasImageSelector,
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
initialCanvasImageSelector,
|
||||
canvasSelector,
|
||||
setStageCoordinates,
|
||||
setStageScale,
|
||||
shouldLockToInitialImageSelector,
|
||||
@ -21,30 +20,23 @@ import {
|
||||
|
||||
const selector = createSelector(
|
||||
[
|
||||
(state: RootState) => state.canvas,
|
||||
activeTabNameSelector,
|
||||
currentCanvasSelector,
|
||||
baseCanvasImageSelector,
|
||||
canvasSelector,
|
||||
initialCanvasImageSelector,
|
||||
shouldLockToInitialImageSelector,
|
||||
],
|
||||
(
|
||||
canvas,
|
||||
activeTabName,
|
||||
currentCanvas,
|
||||
baseCanvasImage,
|
||||
shouldLockToInitialImage
|
||||
) => {
|
||||
(activeTabName, canvas, initialCanvasImage, shouldLockToInitialImage) => {
|
||||
const {
|
||||
isMoveStageKeyHeld,
|
||||
stageScale,
|
||||
stageDimensions,
|
||||
minimumStageScale,
|
||||
} = currentCanvas;
|
||||
} = canvas;
|
||||
return {
|
||||
isMoveStageKeyHeld,
|
||||
stageScale,
|
||||
activeTabName,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
shouldLockToInitialImage,
|
||||
stageDimensions,
|
||||
minimumStageScale,
|
||||
@ -59,7 +51,7 @@ const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
||||
isMoveStageKeyHeld,
|
||||
stageScale,
|
||||
activeTabName,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
shouldLockToInitialImage,
|
||||
stageDimensions,
|
||||
minimumStageScale,
|
||||
@ -72,7 +64,7 @@ const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
||||
activeTabName !== 'outpainting' ||
|
||||
!stageRef.current ||
|
||||
isMoveStageKeyHeld ||
|
||||
!baseCanvasImage
|
||||
!initialCanvasImage
|
||||
)
|
||||
return;
|
||||
|
||||
@ -109,13 +101,14 @@ const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
||||
if (shouldLockToInitialImage) {
|
||||
newCoordinates.x = _.clamp(
|
||||
newCoordinates.x,
|
||||
stageDimensions.width - Math.floor(baseCanvasImage.width * newScale),
|
||||
stageDimensions.width -
|
||||
Math.floor(initialCanvasImage.width * newScale),
|
||||
0
|
||||
);
|
||||
newCoordinates.y = _.clamp(
|
||||
newCoordinates.y,
|
||||
stageDimensions.height -
|
||||
Math.floor(baseCanvasImage.height * newScale),
|
||||
Math.floor(initialCanvasImage.height * newScale),
|
||||
0
|
||||
);
|
||||
}
|
||||
@ -127,7 +120,7 @@ const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
||||
activeTabName,
|
||||
stageRef,
|
||||
isMoveStageKeyHeld,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
stageScale,
|
||||
shouldLockToInitialImage,
|
||||
minimumStageScale,
|
||||
|
@ -1,23 +0,0 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store';
|
||||
import _ from 'lodash';
|
||||
import { currentCanvasSelector, GenericCanvasState } from '../canvasSlice';
|
||||
|
||||
const selector = createSelector(
|
||||
[currentCanvasSelector],
|
||||
(currentCanvas: GenericCanvasState) => {
|
||||
return currentCanvas.stageScale;
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: _.isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const useUnscaleCanvasValue = () => {
|
||||
const stageScale = useAppSelector(selector);
|
||||
return (value: number) => value / stageScale;
|
||||
};
|
||||
|
||||
export default useUnscaleCanvasValue;
|
@ -21,7 +21,7 @@ export const mergeAndUploadCanvas = createAsyncThunk(
|
||||
|
||||
const state = getState() as RootState;
|
||||
|
||||
const stageScale = state.canvas[state.canvas.currentCanvas].stageScale;
|
||||
const stageScale = state.canvas.stageScale;
|
||||
|
||||
if (!canvasImageLayerRef.current) return;
|
||||
|
||||
|
@ -2,16 +2,14 @@ import React from 'react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAICheckbox from 'common/components/IAICheckbox';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
canvasSelector,
|
||||
setShouldDarkenOutsideBoundingBox,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
|
||||
const selector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas: GenericCanvasState) =>
|
||||
currentCanvas.shouldDarkenOutsideBoundingBox
|
||||
canvasSelector,
|
||||
(canvas) => canvas.shouldDarkenOutsideBoundingBox
|
||||
);
|
||||
|
||||
export default function BoundingBoxDarkenOutside() {
|
||||
|
@ -4,7 +4,7 @@ import IAISlider from 'common/components/IAISlider';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
setBoundingBoxDimensions,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
|
||||
@ -12,10 +12,10 @@ import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
|
||||
import _ from 'lodash';
|
||||
|
||||
const boundingBoxDimensionsSelector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas) => {
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
const { stageDimensions, boundingBoxDimensions, shouldLockBoundingBox } =
|
||||
currentCanvas;
|
||||
canvas;
|
||||
return {
|
||||
stageDimensions,
|
||||
boundingBoxDimensions,
|
||||
|
@ -2,14 +2,14 @@ import React from 'react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAICheckbox from 'common/components/IAICheckbox';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
setShouldLockBoundingBox,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
|
||||
const boundingBoxLockSelector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas) => currentCanvas.shouldLockBoundingBox
|
||||
canvasSelector,
|
||||
(canvas) => canvas.shouldLockBoundingBox
|
||||
);
|
||||
|
||||
export default function BoundingBoxLock() {
|
||||
|
@ -3,14 +3,14 @@ import { BiHide, BiShow } from 'react-icons/bi';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
canvasSelector,
|
||||
setShouldShowBoundingBox,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
|
||||
const boundingBoxVisibilitySelector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas) => currentCanvas.shouldShowBoundingBox
|
||||
canvasSelector,
|
||||
(canvas) => canvas.shouldShowBoundingBox
|
||||
);
|
||||
|
||||
export default function BoundingBoxVisibility() {
|
||||
|
@ -3,22 +3,20 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
InpaintingCanvasState,
|
||||
OutpaintingCanvasState,
|
||||
canvasSelector,
|
||||
setClearBrushHistory,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import _ from 'lodash';
|
||||
|
||||
const clearBrushHistorySelector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas) => {
|
||||
const { pastLayerStates, futureLayerStates } = currentCanvas as
|
||||
| InpaintingCanvasState
|
||||
| OutpaintingCanvasState;
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
const { pastLayerStates, futureLayerStates } = canvas;
|
||||
return {
|
||||
mayClearBrushHistory:
|
||||
futureLayerStates.length > 0 || pastLayerStates.length > 0 ? false : true,
|
||||
futureLayerStates.length > 0 || pastLayerStates.length > 0
|
||||
? false
|
||||
: true,
|
||||
};
|
||||
},
|
||||
{
|
||||
|
@ -6,16 +6,15 @@ import IAISwitch from '../../../../common/components/IAISwitch';
|
||||
import IAISlider from '../../../../common/components/IAISlider';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import {
|
||||
currentCanvasSelector,
|
||||
GenericCanvasState,
|
||||
canvasSelector,
|
||||
setInpaintReplace,
|
||||
setShouldUseInpaintReplace,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
|
||||
const canvasInpaintReplaceSelector = createSelector(
|
||||
currentCanvasSelector,
|
||||
(currentCanvas: GenericCanvasState) => {
|
||||
const { inpaintReplace, shouldUseInpaintReplace } = currentCanvas;
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
const { inpaintReplace, shouldUseInpaintReplace } = canvas;
|
||||
return {
|
||||
inpaintReplace,
|
||||
shouldUseInpaintReplace,
|
||||
|
@ -8,7 +8,7 @@ import ImageUploadButton from 'common/components/ImageUploaderButton';
|
||||
import CurrentImageDisplay from 'features/gallery/CurrentImageDisplay';
|
||||
import { OptionsState } from 'features/options/optionsSlice';
|
||||
import {
|
||||
baseCanvasImageSelector,
|
||||
initialCanvasImageSelector,
|
||||
CanvasState,
|
||||
setDoesCanvasNeedScaling,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
@ -16,17 +16,17 @@ import IAICanvas from 'features/canvas/IAICanvas';
|
||||
|
||||
const inpaintingDisplaySelector = createSelector(
|
||||
[
|
||||
baseCanvasImageSelector,
|
||||
initialCanvasImageSelector,
|
||||
(state: RootState) => state.canvas,
|
||||
(state: RootState) => state.options,
|
||||
],
|
||||
(baseCanvasImage, canvas: CanvasState, options: OptionsState) => {
|
||||
(initialCanvasImage, canvas: CanvasState, options: OptionsState) => {
|
||||
const { doesCanvasNeedScaling } = canvas;
|
||||
const { showDualDisplay } = options;
|
||||
return {
|
||||
doesCanvasNeedScaling,
|
||||
showDualDisplay,
|
||||
baseCanvasImage,
|
||||
initialCanvasImage,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -38,7 +38,7 @@ const inpaintingDisplaySelector = createSelector(
|
||||
|
||||
const InpaintingDisplay = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { showDualDisplay, doesCanvasNeedScaling, baseCanvasImage } =
|
||||
const { showDualDisplay, doesCanvasNeedScaling, initialCanvasImage } =
|
||||
useAppSelector(inpaintingDisplaySelector);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
@ -50,7 +50,7 @@ const InpaintingDisplay = () => {
|
||||
return () => window.removeEventListener('resize', resizeCallback);
|
||||
}, [dispatch]);
|
||||
|
||||
const inpaintingComponent = baseCanvasImage ? (
|
||||
const inpaintingComponent = initialCanvasImage ? (
|
||||
<div className="inpainting-main-area">
|
||||
<IAICanvasControls />
|
||||
<div className="inpainting-canvas-area">
|
||||
|
@ -3,12 +3,11 @@ import InpaintingDisplay from './InpaintingDisplay';
|
||||
import InvokeWorkarea from 'features/tabs/InvokeWorkarea';
|
||||
import { useAppDispatch } from 'app/store';
|
||||
import { useEffect } from 'react';
|
||||
import { setCurrentCanvas, setDoesCanvasNeedScaling } from 'features/canvas/canvasSlice';
|
||||
import { setDoesCanvasNeedScaling } from 'features/canvas/canvasSlice';
|
||||
|
||||
export default function InpaintingWorkarea() {
|
||||
const dispatch = useAppDispatch();
|
||||
useEffect(() => {
|
||||
dispatch(setCurrentCanvas('inpainting'));
|
||||
dispatch(setDoesCanvasNeedScaling(true));
|
||||
}, [dispatch]);
|
||||
return (
|
||||
|
@ -3,23 +3,21 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import IAICanvasResizer from 'features/canvas/IAICanvasResizer';
|
||||
import _ from 'lodash';
|
||||
import { useLayoutEffect } from 'react';
|
||||
import { RootState, useAppDispatch, useAppSelector } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store';
|
||||
import ImageUploadButton from 'common/components/ImageUploaderButton';
|
||||
import {
|
||||
CanvasState,
|
||||
canvasSelector,
|
||||
setDoesCanvasNeedScaling,
|
||||
} from 'features/canvas/canvasSlice';
|
||||
import IAICanvas from 'features/canvas/IAICanvas';
|
||||
import IAICanvasOutpaintingControls from 'features/canvas/IAICanvasOutpaintingControls';
|
||||
|
||||
const outpaintingDisplaySelector = createSelector(
|
||||
[(state: RootState) => state.canvas],
|
||||
(canvas: CanvasState) => {
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const {
|
||||
doesCanvasNeedScaling,
|
||||
outpainting: {
|
||||
layerState: { objects },
|
||||
},
|
||||
layerState: { objects },
|
||||
} = canvas;
|
||||
return {
|
||||
doesCanvasNeedScaling,
|
||||
|
@ -3,12 +3,11 @@ import OutpaintingDisplay from './OutpaintingDisplay';
|
||||
import InvokeWorkarea from 'features/tabs/InvokeWorkarea';
|
||||
import { useAppDispatch } from 'app/store';
|
||||
import { useEffect } from 'react';
|
||||
import { setCurrentCanvas, setDoesCanvasNeedScaling } from 'features/canvas/canvasSlice';
|
||||
import { setDoesCanvasNeedScaling } from 'features/canvas/canvasSlice';
|
||||
|
||||
export default function OutpaintingWorkarea() {
|
||||
const dispatch = useAppDispatch();
|
||||
useEffect(() => {
|
||||
dispatch(setCurrentCanvas('outpainting'));
|
||||
dispatch(setDoesCanvasNeedScaling(true));
|
||||
}, [dispatch]);
|
||||
return (
|
||||
|
Loading…
Reference in New Issue
Block a user