mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Improves behaviour when setting init canvas image/reset view
This commit is contained in:
parent
425a1713ab
commit
bb70c32ad5
@ -131,6 +131,7 @@ const IAICanvasOutpaintingControls = () => {
|
|||||||
const handleSelectMoveTool = () => dispatch(setTool('move'));
|
const handleSelectMoveTool = () => dispatch(setTool('move'));
|
||||||
|
|
||||||
const handleResetCanvasView = () => {
|
const handleResetCanvasView = () => {
|
||||||
|
const canvasBaseLayer = getCanvasBaseLayer()
|
||||||
if (!canvasBaseLayer) return;
|
if (!canvasBaseLayer) return;
|
||||||
const clientRect = canvasBaseLayer.getClientRect({
|
const clientRect = canvasBaseLayer.getClientRect({
|
||||||
skipTransform: true,
|
skipTransform: true,
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
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 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 { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
canvasSelector,
|
|
||||||
initialCanvasImageSelector,
|
|
||||||
} from 'features/canvas/store/canvasSelectors';
|
|
||||||
import {
|
import {
|
||||||
setStageCoordinates,
|
setStageCoordinates,
|
||||||
setStageScale,
|
setStageScale,
|
||||||
@ -20,21 +16,12 @@ import {
|
|||||||
} from '../util/constants';
|
} from '../util/constants';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
[activeTabNameSelector, canvasSelector, initialCanvasImageSelector],
|
[canvasSelector],
|
||||||
(activeTabName, canvas, initialCanvasImage) => {
|
(canvas) => {
|
||||||
const {
|
const { isMoveStageKeyHeld, stageScale } = canvas;
|
||||||
isMoveStageKeyHeld,
|
|
||||||
stageScale,
|
|
||||||
stageDimensions,
|
|
||||||
minimumStageScale,
|
|
||||||
} = canvas;
|
|
||||||
return {
|
return {
|
||||||
isMoveStageKeyHeld,
|
isMoveStageKeyHeld,
|
||||||
stageScale,
|
stageScale,
|
||||||
activeTabName,
|
|
||||||
initialCanvasImage,
|
|
||||||
stageDimensions,
|
|
||||||
minimumStageScale,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{ memoizeOptions: { resultEqualityCheck: _.isEqual } }
|
{ memoizeOptions: { resultEqualityCheck: _.isEqual } }
|
||||||
@ -42,20 +29,12 @@ const selector = createSelector(
|
|||||||
|
|
||||||
const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const {
|
const { isMoveStageKeyHeld, stageScale } = useAppSelector(selector);
|
||||||
isMoveStageKeyHeld,
|
|
||||||
stageScale,
|
|
||||||
activeTabName,
|
|
||||||
initialCanvasImage,
|
|
||||||
stageDimensions,
|
|
||||||
minimumStageScale,
|
|
||||||
} = useAppSelector(selector);
|
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
(e: KonvaEventObject<WheelEvent>) => {
|
(e: KonvaEventObject<WheelEvent>) => {
|
||||||
// stop default scrolling
|
// stop default scrolling
|
||||||
if (!stageRef.current || isMoveStageKeyHeld || !initialCanvasImage)
|
if (!stageRef.current || isMoveStageKeyHeld) return;
|
||||||
return;
|
|
||||||
|
|
||||||
e.evt.preventDefault();
|
e.evt.preventDefault();
|
||||||
|
|
||||||
@ -90,7 +69,7 @@ const useCanvasWheel = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
|||||||
dispatch(setStageScale(newScale));
|
dispatch(setStageScale(newScale));
|
||||||
dispatch(setStageCoordinates(newCoordinates));
|
dispatch(setStageCoordinates(newCoordinates));
|
||||||
},
|
},
|
||||||
[stageRef, isMoveStageKeyHeld, initialCanvasImage, stageScale, dispatch]
|
[stageRef, isMoveStageKeyHeld, stageScale, dispatch]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -369,51 +369,6 @@ export const canvasSlice = createSlice({
|
|||||||
const initialCanvasImage =
|
const initialCanvasImage =
|
||||||
state.layerState.objects.find(isCanvasBaseImage);
|
state.layerState.objects.find(isCanvasBaseImage);
|
||||||
|
|
||||||
if (!initialCanvasImage) return;
|
|
||||||
|
|
||||||
const { width: imageWidth, height: imageHeight } = initialCanvasImage;
|
|
||||||
|
|
||||||
const padding = 0.95;
|
|
||||||
|
|
||||||
const newScale = calculateScale(
|
|
||||||
containerWidth,
|
|
||||||
containerHeight,
|
|
||||||
imageWidth,
|
|
||||||
imageHeight,
|
|
||||||
padding
|
|
||||||
);
|
|
||||||
|
|
||||||
const newDimensions = {
|
|
||||||
width: Math.floor(containerWidth),
|
|
||||||
height: Math.floor(containerHeight),
|
|
||||||
};
|
|
||||||
|
|
||||||
const newCoordinates = calculateCoordinates(
|
|
||||||
newDimensions.width,
|
|
||||||
newDimensions.height,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
imageWidth,
|
|
||||||
imageHeight,
|
|
||||||
newScale
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!_.isEqual(state.stageDimensions, newDimensions)) {
|
|
||||||
state.minimumStageScale = newScale;
|
|
||||||
state.stageScale = newScale;
|
|
||||||
state.stageCoordinates = floorCoordinates(newCoordinates);
|
|
||||||
state.stageDimensions = newDimensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.isCanvasInitialized = true;
|
|
||||||
},
|
|
||||||
resizeCanvas: (state) => {
|
|
||||||
const { width: containerWidth, height: containerHeight } =
|
|
||||||
state.canvasContainerDimensions;
|
|
||||||
|
|
||||||
const initialCanvasImage =
|
|
||||||
state.layerState.objects.find(isCanvasBaseImage);
|
|
||||||
|
|
||||||
const newStageDimensions = {
|
const newStageDimensions = {
|
||||||
width: Math.floor(containerWidth),
|
width: Math.floor(containerWidth),
|
||||||
height: Math.floor(containerHeight),
|
height: Math.floor(containerHeight),
|
||||||
@ -441,9 +396,72 @@ export const canvasSlice = createSlice({
|
|||||||
state.stageScale = newScale;
|
state.stageScale = newScale;
|
||||||
|
|
||||||
state.stageCoordinates = newCoordinates;
|
state.stageCoordinates = newCoordinates;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { width: imageWidth, height: imageHeight } = initialCanvasImage;
|
||||||
|
|
||||||
|
const padding = 0.95;
|
||||||
|
|
||||||
|
const newScale = calculateScale(
|
||||||
|
containerWidth,
|
||||||
|
containerHeight,
|
||||||
|
imageWidth,
|
||||||
|
imageHeight,
|
||||||
|
padding
|
||||||
|
);
|
||||||
|
|
||||||
|
const newCoordinates = calculateCoordinates(
|
||||||
|
newStageDimensions.width,
|
||||||
|
newStageDimensions.height,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
imageWidth,
|
||||||
|
imageHeight,
|
||||||
|
newScale
|
||||||
|
);
|
||||||
|
|
||||||
|
state.minimumStageScale = newScale;
|
||||||
|
state.stageScale = newScale;
|
||||||
|
state.stageCoordinates = floorCoordinates(newCoordinates);
|
||||||
state.stageDimensions = newStageDimensions;
|
state.stageDimensions = newStageDimensions;
|
||||||
|
|
||||||
|
state.isCanvasInitialized = true;
|
||||||
|
},
|
||||||
|
resizeCanvas: (state) => {
|
||||||
|
const { width: containerWidth, height: containerHeight } =
|
||||||
|
state.canvasContainerDimensions;
|
||||||
|
|
||||||
|
const newStageDimensions = {
|
||||||
|
width: Math.floor(containerWidth),
|
||||||
|
height: Math.floor(containerHeight),
|
||||||
|
};
|
||||||
|
|
||||||
|
state.stageDimensions = newStageDimensions;
|
||||||
|
|
||||||
|
if (!state.layerState.objects.find(isCanvasBaseImage)) {
|
||||||
|
const newScale = calculateScale(
|
||||||
|
newStageDimensions.width,
|
||||||
|
newStageDimensions.height,
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
STAGE_PADDING_PERCENTAGE
|
||||||
|
);
|
||||||
|
|
||||||
|
const newCoordinates = calculateCoordinates(
|
||||||
|
newStageDimensions.width,
|
||||||
|
newStageDimensions.height,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
newScale
|
||||||
|
);
|
||||||
|
|
||||||
|
state.stageScale = newScale;
|
||||||
|
|
||||||
|
state.stageCoordinates = newCoordinates;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
resetCanvasView: (
|
resetCanvasView: (
|
||||||
state,
|
state,
|
||||||
@ -452,38 +470,57 @@ export const canvasSlice = createSlice({
|
|||||||
}>
|
}>
|
||||||
) => {
|
) => {
|
||||||
const { contentRect } = action.payload;
|
const { contentRect } = action.payload;
|
||||||
|
|
||||||
const baseCanvasImage = state.layerState.objects.find(isCanvasBaseImage);
|
|
||||||
|
|
||||||
if (!baseCanvasImage) return;
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
stageDimensions: { width: stageWidth, height: stageHeight },
|
stageDimensions: { width: stageWidth, height: stageHeight },
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
const { x, y, width, height } = contentRect;
|
const { x, y, width, height } = contentRect;
|
||||||
|
|
||||||
const newScale = calculateScale(
|
if (width !== 0 && height !== 0) {
|
||||||
stageWidth,
|
const newScale = calculateScale(
|
||||||
stageHeight,
|
stageWidth,
|
||||||
width,
|
stageHeight,
|
||||||
height,
|
width,
|
||||||
STAGE_PADDING_PERCENTAGE
|
height,
|
||||||
);
|
STAGE_PADDING_PERCENTAGE
|
||||||
|
);
|
||||||
|
|
||||||
const newCoordinates = calculateCoordinates(
|
const newCoordinates = calculateCoordinates(
|
||||||
stageWidth,
|
stageWidth,
|
||||||
stageHeight,
|
stageHeight,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
newScale
|
newScale
|
||||||
);
|
);
|
||||||
|
|
||||||
state.stageScale = newScale;
|
state.stageScale = newScale;
|
||||||
|
|
||||||
state.stageCoordinates = newCoordinates;
|
state.stageCoordinates = newCoordinates;
|
||||||
|
} else {
|
||||||
|
const newScale = calculateScale(
|
||||||
|
stageWidth,
|
||||||
|
stageHeight,
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
STAGE_PADDING_PERCENTAGE
|
||||||
|
);
|
||||||
|
|
||||||
|
const newCoordinates = calculateCoordinates(
|
||||||
|
stageWidth,
|
||||||
|
stageHeight,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
512,
|
||||||
|
512,
|
||||||
|
newScale
|
||||||
|
);
|
||||||
|
|
||||||
|
state.stageScale = newScale;
|
||||||
|
|
||||||
|
state.stageCoordinates = newCoordinates;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
nextStagingAreaImage: (state) => {
|
nextStagingAreaImage: (state) => {
|
||||||
const currentIndex = state.layerState.stagingArea.selectedImageIndex;
|
const currentIndex = state.layerState.stagingArea.selectedImageIndex;
|
||||||
|
@ -23,10 +23,13 @@ import {
|
|||||||
import * as InvokeAI from 'app/invokeai';
|
import * as InvokeAI from 'app/invokeai';
|
||||||
import * as ContextMenu from '@radix-ui/react-context-menu';
|
import * as ContextMenu from '@radix-ui/react-context-menu';
|
||||||
import {
|
import {
|
||||||
|
resetCanvasView,
|
||||||
|
resizeAndScaleCanvas,
|
||||||
setDoesCanvasNeedScaling,
|
setDoesCanvasNeedScaling,
|
||||||
setInitialCanvasImage,
|
setInitialCanvasImage,
|
||||||
} from 'features/canvas/store/canvasSlice';
|
} from 'features/canvas/store/canvasSlice';
|
||||||
import { hoverableImageSelector } from './gallerySliceSelectors';
|
import { hoverableImageSelector } from './gallerySliceSelectors';
|
||||||
|
import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider';
|
||||||
|
|
||||||
interface HoverableImageProps {
|
interface HoverableImageProps {
|
||||||
image: InvokeAI.Image;
|
image: InvokeAI.Image;
|
||||||
@ -99,7 +102,8 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
|||||||
if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false));
|
if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false));
|
||||||
|
|
||||||
dispatch(setInitialCanvasImage(image));
|
dispatch(setInitialCanvasImage(image));
|
||||||
dispatch(setDoesCanvasNeedScaling(true));
|
|
||||||
|
dispatch(resizeAndScaleCanvas());
|
||||||
|
|
||||||
if (activeTabName !== 'unifiedCanvas') {
|
if (activeTabName !== 'unifiedCanvas') {
|
||||||
dispatch(setActiveTab('unifiedCanvas'));
|
dispatch(setActiveTab('unifiedCanvas'));
|
||||||
|
Loading…
Reference in New Issue
Block a user