mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): canvas perf improvements
This commit is contained in:
parent
e108a2302e
commit
6f354f16ba
@ -21,12 +21,11 @@ type InpaintingCanvasLinesProps = GroupConfig;
|
|||||||
* Uses globalCompositeOperation to handle the brush and eraser tools.
|
* Uses globalCompositeOperation to handle the brush and eraser tools.
|
||||||
*/
|
*/
|
||||||
const IAICanvasLines = (props: InpaintingCanvasLinesProps) => {
|
const IAICanvasLines = (props: InpaintingCanvasLinesProps) => {
|
||||||
const { ...rest } = props;
|
const objects = useAppSelector((state) => state.canvas.layerState.objects);
|
||||||
const lines = useAppSelector(canvasLinesSelector);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group listening={false} {...rest}>
|
<Group listening={false} {...props}>
|
||||||
{lines.map((line, i) => (
|
{objects.filter(isCanvasMaskLine).map((line, i) => (
|
||||||
<Line
|
<Line
|
||||||
key={i}
|
key={i}
|
||||||
points={line.points}
|
points={line.points}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
|
||||||
import { stateSelector } from 'app/store/store';
|
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import {
|
import {
|
||||||
isCanvasBaseImage,
|
isCanvasBaseImage,
|
||||||
@ -13,21 +11,8 @@ import { Group, Line, Rect } from 'react-konva';
|
|||||||
|
|
||||||
import IAICanvasImage from './IAICanvasImage';
|
import IAICanvasImage from './IAICanvasImage';
|
||||||
|
|
||||||
const selector = createMemoizedSelector([stateSelector], ({ canvas }) => {
|
|
||||||
const {
|
|
||||||
layerState: { objects },
|
|
||||||
} = canvas;
|
|
||||||
return {
|
|
||||||
objects,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const IAICanvasObjectRenderer = () => {
|
const IAICanvasObjectRenderer = () => {
|
||||||
const { objects } = useAppSelector(selector);
|
const objects = useAppSelector((state) => state.canvas.layerState.objects);
|
||||||
|
|
||||||
if (!objects) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group name="outpainting-objects" listening={false}>
|
<Group name="outpainting-objects" listening={false}>
|
||||||
|
@ -39,7 +39,6 @@ const selector = createMemoizedSelector([stateSelector], ({ canvas }) => {
|
|||||||
type Props = GroupConfig;
|
type Props = GroupConfig;
|
||||||
|
|
||||||
const IAICanvasStagingArea = (props: Props) => {
|
const IAICanvasStagingArea = (props: Props) => {
|
||||||
const { ...rest } = props;
|
|
||||||
const {
|
const {
|
||||||
currentStagingAreaImage,
|
currentStagingAreaImage,
|
||||||
shouldShowStagingImage,
|
shouldShowStagingImage,
|
||||||
@ -51,7 +50,7 @@ const IAICanvasStagingArea = (props: Props) => {
|
|||||||
} = useAppSelector(selector);
|
} = useAppSelector(selector);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group {...rest}>
|
<Group {...props}>
|
||||||
{shouldShowStagingImage && currentStagingAreaImage && (
|
{shouldShowStagingImage && currentStagingAreaImage && (
|
||||||
<IAICanvasImage canvasImage={currentStagingAreaImage} />
|
<IAICanvasImage canvasImage={currentStagingAreaImage} />
|
||||||
)}
|
)}
|
||||||
|
@ -110,7 +110,6 @@ const canvasBrushPreviewSelector = createMemoizedSelector(
|
|||||||
* Draws a black circle around the canvas brush preview.
|
* Draws a black circle around the canvas brush preview.
|
||||||
*/
|
*/
|
||||||
const IAICanvasToolPreview = (props: GroupConfig) => {
|
const IAICanvasToolPreview = (props: GroupConfig) => {
|
||||||
const { ...rest } = props;
|
|
||||||
const {
|
const {
|
||||||
brushX,
|
brushX,
|
||||||
brushY,
|
brushY,
|
||||||
@ -133,7 +132,7 @@ const IAICanvasToolPreview = (props: GroupConfig) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group listening={false} {...clip} {...rest}>
|
<Group listening={false} {...clip} {...props}>
|
||||||
{tool === 'colorPicker' ? (
|
{tool === 'colorPicker' ? (
|
||||||
<>
|
<>
|
||||||
<Circle
|
<Circle
|
||||||
@ -143,6 +142,7 @@ const IAICanvasToolPreview = (props: GroupConfig) => {
|
|||||||
stroke={brushColorString}
|
stroke={brushColorString}
|
||||||
strokeWidth={COLOR_PICKER_STROKE_RADIUS}
|
strokeWidth={COLOR_PICKER_STROKE_RADIUS}
|
||||||
strokeScaleEnabled={false}
|
strokeScaleEnabled={false}
|
||||||
|
listening={false}
|
||||||
/>
|
/>
|
||||||
<Circle
|
<Circle
|
||||||
x={brushX}
|
x={brushX}
|
||||||
@ -151,6 +151,7 @@ const IAICanvasToolPreview = (props: GroupConfig) => {
|
|||||||
stroke={colorPickerColorString}
|
stroke={colorPickerColorString}
|
||||||
strokeWidth={COLOR_PICKER_STROKE_RADIUS}
|
strokeWidth={COLOR_PICKER_STROKE_RADIUS}
|
||||||
strokeScaleEnabled={false}
|
strokeScaleEnabled={false}
|
||||||
|
listening={false}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
@ -163,6 +164,7 @@ const IAICanvasToolPreview = (props: GroupConfig) => {
|
|||||||
globalCompositeOperation={
|
globalCompositeOperation={
|
||||||
tool === 'eraser' ? 'destination-out' : 'source-out'
|
tool === 'eraser' ? 'destination-out' : 'source-out'
|
||||||
}
|
}
|
||||||
|
listening={false}
|
||||||
/>
|
/>
|
||||||
<Circle
|
<Circle
|
||||||
x={brushX}
|
x={brushX}
|
||||||
|
@ -125,7 +125,7 @@ const IAICanvasMaskOptions = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvPopover>
|
<InvPopover isLazy>
|
||||||
<InvPopoverTrigger>
|
<InvPopoverTrigger>
|
||||||
<InvIconButton
|
<InvIconButton
|
||||||
aria-label={t('unifiedCanvas.maskingOptions')}
|
aria-label={t('unifiedCanvas.maskingOptions')}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
|
||||||
import { stateSelector } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
import {
|
import {
|
||||||
@ -9,50 +7,42 @@ import {
|
|||||||
import type { KonvaEventObject } from 'konva/lib/Node';
|
import type { KonvaEventObject } from 'konva/lib/Node';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
const selector = createMemoizedSelector(
|
|
||||||
[stateSelector, isStagingSelector],
|
|
||||||
({ canvas }, isStaging) => {
|
|
||||||
const { tool, isMovingBoundingBox } = canvas;
|
|
||||||
return {
|
|
||||||
tool,
|
|
||||||
isStaging,
|
|
||||||
isMovingBoundingBox,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const useCanvasDrag = () => {
|
const useCanvasDrag = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { tool, isStaging, isMovingBoundingBox } = useAppSelector(selector);
|
const tool = useAppSelector((state) => state.canvas.tool);
|
||||||
|
const isMovingBoundingBox = useAppSelector(
|
||||||
|
(state) => state.canvas.isMovingBoundingBox
|
||||||
|
);
|
||||||
|
const isStaging = useAppSelector(isStagingSelector);
|
||||||
|
|
||||||
return {
|
const handleDragStart = useCallback(() => {
|
||||||
handleDragStart: useCallback(() => {
|
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dispatch(setIsMovingStage(true));
|
||||||
|
}, [dispatch, isMovingBoundingBox, isStaging, tool]);
|
||||||
|
|
||||||
|
const handleDragMove = useCallback(
|
||||||
|
(e: KonvaEventObject<MouseEvent>) => {
|
||||||
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
|
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch(setIsMovingStage(true));
|
|
||||||
}, [dispatch, isMovingBoundingBox, isStaging, tool]),
|
|
||||||
|
|
||||||
handleDragMove: useCallback(
|
const newCoordinates = { x: e.target.x(), y: e.target.y() };
|
||||||
(e: KonvaEventObject<MouseEvent>) => {
|
|
||||||
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newCoordinates = { x: e.target.x(), y: e.target.y() };
|
dispatch(setStageCoordinates(newCoordinates));
|
||||||
|
},
|
||||||
|
[dispatch, isMovingBoundingBox, isStaging, tool]
|
||||||
|
);
|
||||||
|
|
||||||
dispatch(setStageCoordinates(newCoordinates));
|
const handleDragEnd = useCallback(() => {
|
||||||
},
|
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
|
||||||
[dispatch, isMovingBoundingBox, isStaging, tool]
|
return;
|
||||||
),
|
}
|
||||||
|
dispatch(setIsMovingStage(false));
|
||||||
|
}, [dispatch, isMovingBoundingBox, isStaging, tool]);
|
||||||
|
|
||||||
handleDragEnd: useCallback(() => {
|
return { handleDragStart, handleDragMove, handleDragEnd };
|
||||||
if (!((tool === 'move' || isStaging) && !isMovingBoundingBox)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dispatch(setIsMovingStage(false));
|
|
||||||
}, [dispatch, isMovingBoundingBox, isStaging, tool]),
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useCanvasDrag;
|
export default useCanvasDrag;
|
||||||
|
Loading…
Reference in New Issue
Block a user