InvokeAI/frontend/src/features/canvas/components/IAICanvasToolPreview.tsx
2022-11-27 03:35:49 +13:00

218 lines
6.4 KiB
TypeScript

import { createSelector } from '@reduxjs/toolkit';
import { GroupConfig } from 'konva/lib/Group';
import _ from 'lodash';
import { Circle, Group, Rect } from 'react-konva';
import { useAppSelector } from 'app/store';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { rgbaColorToString } from 'features/canvas/util/colorToString';
import {
COLOR_PICKER_SIZE,
COLOR_PICKER_STROKE_RADIUS,
} from '../util/constants';
const canvasBrushPreviewSelector = createSelector(
canvasSelector,
(canvas) => {
const {
cursorPosition,
stageDimensions: { width, height },
brushSize,
colorPickerColor,
maskColor,
brushColor,
tool,
layer,
shouldShowBrush,
isMovingBoundingBox,
isTransformingBoundingBox,
stageScale,
} = canvas;
let fill = '';
if (layer === 'mask') {
fill = rgbaColorToString({ ...maskColor, a: 0.5 });
} else if (tool === 'colorPicker') {
fill = rgbaColorToString(colorPickerColor);
} else {
fill = rgbaColorToString(brushColor);
}
return {
cursorPosition,
width,
height,
radius: brushSize / 2,
colorPickerSize: COLOR_PICKER_SIZE / stageScale,
colorPickerOffset: COLOR_PICKER_SIZE / 2 / stageScale,
colorPickerCornerRadius: COLOR_PICKER_SIZE / 5 / stageScale,
colorPickerOuterRadius: COLOR_PICKER_SIZE / stageScale,
colorPickerInnerRadius:
(COLOR_PICKER_SIZE - COLOR_PICKER_STROKE_RADIUS + 1) / stageScale,
maskColorString: rgbaColorToString({ ...maskColor, a: 0.5 }),
brushColorString: rgbaColorToString(brushColor),
colorPickerColorString: rgbaColorToString(colorPickerColor),
tool,
shouldShowBrush,
shouldDrawBrushPreview:
!(
isMovingBoundingBox ||
isTransformingBoundingBox ||
!cursorPosition
) && shouldShowBrush,
strokeWidth: 1.5 / stageScale,
dotRadius: 1.5 / stageScale,
};
},
{
memoizeOptions: {
resultEqualityCheck: _.isEqual,
},
}
);
/**
* Draws a black circle around the canvas brush preview.
*/
const IAICanvasToolPreview = (props: GroupConfig) => {
const { ...rest } = props;
const {
cursorPosition,
width,
height,
radius,
maskColorString,
tool,
shouldDrawBrushPreview,
dotRadius,
strokeWidth,
colorPickerSize,
colorPickerOffset,
colorPickerCornerRadius,
brushColorString,
colorPickerColorString,
colorPickerInnerRadius,
colorPickerOuterRadius,
} = useAppSelector(canvasBrushPreviewSelector);
if (!shouldDrawBrushPreview) return null;
return (
<Group listening={false} {...rest}>
{tool === 'colorPicker' ? (
<>
<Circle
x={cursorPosition ? cursorPosition.x : width / 2}
y={cursorPosition ? cursorPosition.y : height / 2}
radius={colorPickerOuterRadius}
stroke={brushColorString}
strokeWidth={COLOR_PICKER_STROKE_RADIUS}
strokeScaleEnabled={false}
/>
<Circle
x={cursorPosition ? cursorPosition.x : width / 2}
y={cursorPosition ? cursorPosition.y : height / 2}
radius={colorPickerInnerRadius}
stroke={colorPickerColorString}
strokeWidth={COLOR_PICKER_STROKE_RADIUS}
strokeScaleEnabled={false}
/>
</>
) : (
<>
<Circle
x={cursorPosition ? cursorPosition.x : width / 2}
y={cursorPosition ? cursorPosition.y : height / 2}
radius={radius}
fill={brushColorString}
globalCompositeOperation={
tool === 'eraser' ? 'destination-out' : 'source-over'
}
/>
<Circle
x={cursorPosition ? cursorPosition.x : width / 2}
y={cursorPosition ? cursorPosition.y : height / 2}
radius={radius}
stroke={'rgba(255,255,255,0.4)'}
strokeWidth={strokeWidth * 2}
strokeEnabled={true}
listening={false}
/>
<Circle
x={cursorPosition ? cursorPosition.x : width / 2}
y={cursorPosition ? cursorPosition.y : height / 2}
radius={radius}
stroke={'rgba(0,0,0,1)'}
strokeWidth={strokeWidth}
strokeEnabled={true}
listening={false}
/>
</>
)}
<Circle
x={cursorPosition ? cursorPosition.x : width / 2}
y={cursorPosition ? cursorPosition.y : height / 2}
radius={dotRadius * 2}
fill={'rgba(255,255,255,0.4)'}
listening={false}
/>
<Circle
x={cursorPosition ? cursorPosition.x : width / 2}
y={cursorPosition ? cursorPosition.y : height / 2}
radius={dotRadius}
fill={'rgba(0,0,0,1)'}
listening={false}
/>
</Group>
);
};
export default IAICanvasToolPreview;
{
/* <>
<Rect
x={
cursorPosition ? cursorPosition.x - colorPickerOffset : width / 2
}
y={
cursorPosition ? cursorPosition.y - colorPickerOffset : height / 2
}
width={colorPickerSize}
height={colorPickerSize}
fill={brushColorString}
cornerRadius={colorPickerCornerRadius}
listening={false}
/>
<Rect
x={
cursorPosition ? cursorPosition.x - colorPickerOffset : width / 2
}
y={
cursorPosition ? cursorPosition.y - colorPickerOffset : height / 2
}
width={colorPickerSize}
height={colorPickerSize}
cornerRadius={colorPickerCornerRadius}
stroke={'rgba(255,255,255,0.4)'}
strokeWidth={strokeWidth * 2}
strokeEnabled={true}
listening={false}
/>
<Rect
x={
cursorPosition ? cursorPosition.x - colorPickerOffset : width / 2
}
y={
cursorPosition ? cursorPosition.y - colorPickerOffset : height / 2
}
width={colorPickerSize}
height={colorPickerSize}
cornerRadius={colorPickerCornerRadius}
stroke={'rgba(0,0,0,1)'}
strokeWidth={strokeWidth}
strokeEnabled={true}
listening={false}
/>
</> */
}