mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): create new line when mouse held down, leaves canvas and comes back over
This commit is contained in:
@ -15,6 +15,7 @@ import {
|
|||||||
} from 'features/regionalPrompts/store/regionalPromptsSlice';
|
} from 'features/regionalPrompts/store/regionalPromptsSlice';
|
||||||
import type Konva from 'konva';
|
import type Konva from 'konva';
|
||||||
import type { KonvaEventObject } from 'konva/lib/Node';
|
import type { KonvaEventObject } from 'konva/lib/Node';
|
||||||
|
import type { Vector2d } from 'konva/lib/types';
|
||||||
import { useCallback, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
|
|
||||||
const getIsFocused = (stage: Konva.Stage) => {
|
const getIsFocused = (stage: Konva.Stage) => {
|
||||||
@ -23,21 +24,26 @@ const getIsFocused = (stage: Konva.Stage) => {
|
|||||||
|
|
||||||
export const getScaledFlooredCursorPosition = (stage: Konva.Stage) => {
|
export const getScaledFlooredCursorPosition = (stage: Konva.Stage) => {
|
||||||
const pointerPosition = stage.getPointerPosition();
|
const pointerPosition = stage.getPointerPosition();
|
||||||
|
|
||||||
const stageTransform = stage.getAbsoluteTransform().copy();
|
const stageTransform = stage.getAbsoluteTransform().copy();
|
||||||
|
|
||||||
if (!pointerPosition || !stageTransform) {
|
if (!pointerPosition || !stageTransform) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const scaledCursorPosition = stageTransform.invert().point(pointerPosition);
|
const scaledCursorPosition = stageTransform.invert().point(pointerPosition);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: Math.floor(scaledCursorPosition.x),
|
x: Math.floor(scaledCursorPosition.x),
|
||||||
y: Math.floor(scaledCursorPosition.y),
|
y: Math.floor(scaledCursorPosition.y),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const syncCursorPos = (stage: Konva.Stage): Vector2d | null => {
|
||||||
|
const pos = getScaledFlooredCursorPosition(stage);
|
||||||
|
if (!pos) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$cursorPosition.set(pos);
|
||||||
|
return pos;
|
||||||
|
};
|
||||||
|
|
||||||
export const useMouseEvents = () => {
|
export const useMouseEvents = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const selectedLayerId = useAppSelector((s) => s.regionalPrompts.present.selectedLayerId);
|
const selectedLayerId = useAppSelector((s) => s.regionalPrompts.present.selectedLayerId);
|
||||||
@ -52,7 +58,7 @@ export const useMouseEvents = () => {
|
|||||||
if (!stage) {
|
if (!stage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const pos = $cursorPosition.get();
|
const pos = syncCursorPos(stage);
|
||||||
if (!pos) {
|
if (!pos) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -66,7 +72,7 @@ export const useMouseEvents = () => {
|
|||||||
dispatch(
|
dispatch(
|
||||||
maskLayerLineAdded({
|
maskLayerLineAdded({
|
||||||
layerId: selectedLayerId,
|
layerId: selectedLayerId,
|
||||||
points: [Math.floor(pos.x), Math.floor(pos.y), Math.floor(pos.x), Math.floor(pos.y)],
|
points: [pos.x, pos.y, pos.x, pos.y],
|
||||||
tool,
|
tool,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -109,33 +115,46 @@ export const useMouseEvents = () => {
|
|||||||
if (!stage) {
|
if (!stage) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const pos = getScaledFlooredCursorPosition(stage);
|
const pos = syncCursorPos(stage);
|
||||||
if (!pos || !selectedLayerId) {
|
if (!pos || !selectedLayerId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$cursorPosition.set(pos);
|
|
||||||
if (getIsFocused(stage) && $isMouseOver.get() && $isMouseDown.get() && (tool === 'brush' || tool === 'eraser')) {
|
if (getIsFocused(stage) && $isMouseOver.get() && $isMouseDown.get() && (tool === 'brush' || tool === 'eraser')) {
|
||||||
if (lastCursorPosRef.current) {
|
if (lastCursorPosRef.current) {
|
||||||
if (Math.hypot(lastCursorPosRef.current[0] - pos.x, lastCursorPosRef.current[1] - pos.y) < 20) {
|
if (Math.hypot(lastCursorPosRef.current[0] - pos.x, lastCursorPosRef.current[1] - pos.y) < 20) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastCursorPosRef.current = [Math.floor(pos.x), Math.floor(pos.y)];
|
lastCursorPosRef.current = [pos.x, pos.y];
|
||||||
dispatch(maskLayerPointsAdded({ layerId: selectedLayerId, point: lastCursorPosRef.current }));
|
dispatch(maskLayerPointsAdded({ layerId: selectedLayerId, point: lastCursorPosRef.current }));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[dispatch, selectedLayerId, tool]
|
[dispatch, selectedLayerId, tool]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onMouseLeave = useCallback((e: KonvaEventObject<MouseEvent | TouchEvent>) => {
|
const onMouseLeave = useCallback(
|
||||||
const stage = e.target.getStage();
|
(e: KonvaEventObject<MouseEvent | TouchEvent>) => {
|
||||||
if (!stage) {
|
const stage = e.target.getStage();
|
||||||
return;
|
if (!stage) {
|
||||||
}
|
return;
|
||||||
$isMouseOver.set(false);
|
}
|
||||||
$isMouseDown.set(false);
|
const pos = syncCursorPos(stage);
|
||||||
$cursorPosition.set(null);
|
if (
|
||||||
}, []);
|
pos &&
|
||||||
|
selectedLayerId &&
|
||||||
|
getIsFocused(stage) &&
|
||||||
|
$isMouseOver.get() &&
|
||||||
|
$isMouseDown.get() &&
|
||||||
|
(tool === 'brush' || tool === 'eraser')
|
||||||
|
) {
|
||||||
|
dispatch(maskLayerPointsAdded({ layerId: selectedLayerId, point: [pos.x, pos.y] }));
|
||||||
|
}
|
||||||
|
$isMouseOver.set(false);
|
||||||
|
$isMouseDown.set(false);
|
||||||
|
$cursorPosition.set(null);
|
||||||
|
},
|
||||||
|
[selectedLayerId, tool, dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
const onMouseEnter = useCallback(
|
const onMouseEnter = useCallback(
|
||||||
(e: KonvaEventObject<MouseEvent>) => {
|
(e: KonvaEventObject<MouseEvent>) => {
|
||||||
@ -144,7 +163,7 @@ export const useMouseEvents = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$isMouseOver.set(true);
|
$isMouseOver.set(true);
|
||||||
const pos = $cursorPosition.get();
|
const pos = syncCursorPos(stage);
|
||||||
if (!pos) {
|
if (!pos) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -162,7 +181,7 @@ export const useMouseEvents = () => {
|
|||||||
dispatch(
|
dispatch(
|
||||||
maskLayerLineAdded({
|
maskLayerLineAdded({
|
||||||
layerId: selectedLayerId,
|
layerId: selectedLayerId,
|
||||||
points: [Math.floor(pos.x), Math.floor(pos.y), Math.floor(pos.x), Math.floor(pos.y)],
|
points: [pos.x, pos.y, pos.x, pos.y],
|
||||||
tool,
|
tool,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user