fix(ui): edge cases when holding shift and drawing lines

This commit is contained in:
psychedelicious 2024-07-05 11:03:36 +10:00
parent 36862be2aa
commit 4111b3f1aa

View File

@ -6,6 +6,7 @@ import type {
LayerEntity, LayerEntity,
Position, Position,
RegionEntity, RegionEntity,
Tool,
} from 'features/controlLayers/store/types'; } from 'features/controlLayers/store/types';
import { isDrawableEntity, isDrawableEntityAdapter } from 'features/controlLayers/store/types'; import { isDrawableEntity, isDrawableEntityAdapter } from 'features/controlLayers/store/types';
import type Konva from 'konva'; import type Konva from 'konva';
@ -64,6 +65,49 @@ const getNextPoint = (
return currentPos; return currentPos;
}; };
const getLastPointOfLine = (points: number[]): Position | null => {
if (points.length < 2) {
return null;
}
const x = points[points.length - 2];
const y = points[points.length - 1];
if (x === undefined || y === undefined) {
return null;
}
return { x, y };
};
const getLastPointOfLastLineOfEntity = (
entity: LayerEntity | RegionEntity | InpaintMaskEntity,
tool: Tool
): Position | null => {
const lastObject = entity.objects[entity.objects.length - 1];
if (!lastObject) {
return null;
}
if (
!(
(lastObject.type === 'brush_line' && tool === 'brush') ||
(lastObject.type === 'eraser_line' && tool === 'eraser')
)
) {
// If the last object type and current tool do not match, we cannot continue the line
return null;
}
if (lastObject.points.length < 2) {
return null;
}
const x = lastObject.points[lastObject.points.length - 2];
const y = lastObject.points[lastObject.points.length - 1];
if (x === undefined || y === undefined) {
return null;
}
return { x, y };
};
export const setStageEventHandlers = (manager: CanvasManager): (() => void) => { export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
const { stage, stateApi, getSelectedEntityAdapter } = manager; const { stage, stateApi, getSelectedEntityAdapter } = manager;
const { const {
@ -75,7 +119,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
setLastMouseDownPos, setLastMouseDownPos,
getLastCursorPos, getLastCursorPos,
setLastCursorPos, setLastCursorPos,
getLastAddedPoint, // getLastAddedPoint,
setLastAddedPoint, setLastAddedPoint,
setStageAttrs, setStageAttrs,
getSelectedEntity, getSelectedEntity,
@ -137,10 +181,9 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
setLastMouseDownPos(pos); setLastMouseDownPos(pos);
if (toolState.selected === 'brush') { if (toolState.selected === 'brush') {
if (e.evt.shiftKey) { const lastLinePoint = getLastPointOfLastLineOfEntity(selectedEntity, toolState.selected);
const lastAddedPoint = getLastAddedPoint(); if (e.evt.shiftKey && lastLinePoint) {
// Create a straight line if holding shift // Create a straight line from the last line point
if (lastAddedPoint) {
if (selectedEntityAdapter.getDrawingBuffer()) { if (selectedEntityAdapter.getDrawingBuffer()) {
selectedEntityAdapter.finalizeDrawingBuffer(); selectedEntityAdapter.finalizeDrawingBuffer();
} }
@ -148,8 +191,9 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
id: getBrushLineId(selectedEntityAdapter.id, uuidv4()), id: getBrushLineId(selectedEntityAdapter.id, uuidv4()),
type: 'brush_line', type: 'brush_line',
points: [ points: [
lastAddedPoint.x - selectedEntity.x, // The last point of the last line is already normalized to the entity's coordinates
lastAddedPoint.y - selectedEntity.y, lastLinePoint.x,
lastLinePoint.y,
pos.x - selectedEntity.x, pos.x - selectedEntity.x,
pos.y - selectedEntity.y, pos.y - selectedEntity.y,
], ],
@ -157,7 +201,6 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
color: getCurrentFill(), color: getCurrentFill(),
clip: getClip(selectedEntity), clip: getClip(selectedEntity),
}); });
}
} else { } else {
if (selectedEntityAdapter.getDrawingBuffer()) { if (selectedEntityAdapter.getDrawingBuffer()) {
selectedEntityAdapter.finalizeDrawingBuffer(); selectedEntityAdapter.finalizeDrawingBuffer();
@ -180,10 +223,9 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
} }
if (toolState.selected === 'eraser') { if (toolState.selected === 'eraser') {
if (e.evt.shiftKey) { const lastLinePoint = getLastPointOfLastLineOfEntity(selectedEntity, toolState.selected);
// Create a straight line if holding shift if (e.evt.shiftKey && lastLinePoint) {
const lastAddedPoint = getLastAddedPoint(); // Create a straight line from the last line point
if (lastAddedPoint) {
if (selectedEntityAdapter.getDrawingBuffer()) { if (selectedEntityAdapter.getDrawingBuffer()) {
selectedEntityAdapter.finalizeDrawingBuffer(); selectedEntityAdapter.finalizeDrawingBuffer();
} }
@ -191,15 +233,15 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
id: getBrushLineId(selectedEntityAdapter.id, uuidv4()), id: getBrushLineId(selectedEntityAdapter.id, uuidv4()),
type: 'eraser_line', type: 'eraser_line',
points: [ points: [
lastAddedPoint.x - selectedEntity.x, // The last point of the last line is already normalized to the entity's coordinates
lastAddedPoint.y - selectedEntity.y, lastLinePoint.x,
lastLinePoint.y,
pos.x - selectedEntity.x, pos.x - selectedEntity.x,
pos.y - selectedEntity.y, pos.y - selectedEntity.y,
], ],
strokeWidth: toolState.eraser.width, strokeWidth: toolState.eraser.width,
clip: getClip(selectedEntity), clip: getClip(selectedEntity),
}); });
}
} else { } else {
if (selectedEntityAdapter.getDrawingBuffer()) { if (selectedEntityAdapter.getDrawingBuffer()) {
selectedEntityAdapter.finalizeDrawingBuffer(); selectedEntityAdapter.finalizeDrawingBuffer();
@ -308,8 +350,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
const drawingBuffer = selectedEntityAdapter.getDrawingBuffer(); const drawingBuffer = selectedEntityAdapter.getDrawingBuffer();
if (drawingBuffer) { if (drawingBuffer) {
if (drawingBuffer?.type === 'brush_line') { if (drawingBuffer?.type === 'brush_line') {
const lastAddedPoint = getLastAddedPoint(); const nextPoint = getNextPoint(pos, toolState, getLastPointOfLine(drawingBuffer.points));
const nextPoint = getNextPoint(pos, toolState, lastAddedPoint);
if (nextPoint) { if (nextPoint) {
drawingBuffer.points.push(nextPoint.x - selectedEntity.x, nextPoint.y - selectedEntity.y); drawingBuffer.points.push(nextPoint.x - selectedEntity.x, nextPoint.y - selectedEntity.y);
await selectedEntityAdapter.setDrawingBuffer(drawingBuffer); await selectedEntityAdapter.setDrawingBuffer(drawingBuffer);
@ -343,8 +384,7 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => {
const drawingBuffer = selectedEntityAdapter.getDrawingBuffer(); const drawingBuffer = selectedEntityAdapter.getDrawingBuffer();
if (drawingBuffer) { if (drawingBuffer) {
if (drawingBuffer.type === 'eraser_line') { if (drawingBuffer.type === 'eraser_line') {
const lastAddedPoint = getLastAddedPoint(); const nextPoint = getNextPoint(pos, toolState, getLastPointOfLine(drawingBuffer.points));
const nextPoint = getNextPoint(pos, toolState, lastAddedPoint);
if (nextPoint) { if (nextPoint) {
drawingBuffer.points.push(nextPoint.x - selectedEntity.x, nextPoint.y - selectedEntity.y); drawingBuffer.points.push(nextPoint.x - selectedEntity.x, nextPoint.y - selectedEntity.y);
await selectedEntityAdapter.setDrawingBuffer(drawingBuffer); await selectedEntityAdapter.setDrawingBuffer(drawingBuffer);