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