mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
218 lines
6.4 KiB
TypeScript
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}
|
|
/>
|
|
</> */
|
|
}
|