From e0d84743bee7a322a24a04396deb2ef8bdd647b0 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:12:36 +1000 Subject: [PATCH] fix(ui): do not allow drawing if layer disabled --- .../controlLayers/konva/CanvasTool.ts | 41 +- .../features/controlLayers/konva/events.ts | 358 +++++++++--------- 2 files changed, 193 insertions(+), 206 deletions(-) diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasTool.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasTool.ts index 49afdca9c6..28dd794470 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasTool.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasTool.ts @@ -194,31 +194,36 @@ export class CanvasTool { const tool = toolState.selected; - const isDrawable = selectedEntity && isDrawableEntity(selectedEntity.state); + const isDrawable = selectedEntity && selectedEntity.state.isEnabled && isDrawableEntity(selectedEntity.state); // Update the stage's pointer style - if (tool === 'view') { - // View gets a hand + if (Boolean(this.manager.stateApi.$transformingEntity.get()) || renderedEntityCount === 0) { + // We are transforming and/or have no layers, so we should not render any tool + stage.container().style.cursor = 'default'; + } else if (tool === 'view') { + // view tool gets a hand stage.container().style.cursor = isMouseDown ? 'grabbing' : 'grab'; - } else if (renderedEntityCount === 0) { - // We have no layers, so we should not render any tool - stage.container().style.cursor = 'default'; - } else if (!isDrawable) { - // Non-drawable layers don't have tools - stage.container().style.cursor = 'not-allowed'; - } else if (tool === 'move' || Boolean(this.manager.stateApi.$transformingEntity.get())) { - // Move tool gets a pointer - stage.container().style.cursor = 'default'; - } else if (tool === 'rect') { - // Rect gets a crosshair - stage.container().style.cursor = 'crosshair'; - } else if (tool === 'brush' || tool === 'eraser') { - // Hide the native cursor and use the konva-rendered brush preview - stage.container().style.cursor = 'none'; + // Bbox tool gets default } else if (tool === 'bbox') { stage.container().style.cursor = 'default'; } else if (tool === 'eyeDropper') { + // Eyedropper gets none stage.container().style.cursor = 'none'; + } else if (isDrawable) { + if (tool === 'move') { + // Move gets default arrow + stage.container().style.cursor = 'default'; + } else if (tool === 'rect') { + // Rect gets a crosshair + stage.container().style.cursor = 'crosshair'; + } else if (tool === 'brush' || tool === 'eraser') { + // Hide the native cursor and use the konva-rendered brush preview + stage.container().style.cursor = 'none'; + } + } else { + // isDrawable === 'false' + // Non-drawable layers don't have tools + stage.container().style.cursor = 'not-allowed'; } stage.draggable(tool === 'view'); diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/events.ts b/invokeai/frontend/web/src/features/controlLayers/konva/events.ts index c0e94109f2..a55dc3752d 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/events.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/events.ts @@ -15,7 +15,6 @@ import type { RgbaColor, Tool, } from 'features/controlLayers/store/types'; -import { isDrawableEntity, isDrawableEntityAdapter } from 'features/controlLayers/store/types'; import type Konva from 'konva'; import type { KonvaEventObject } from 'konva/lib/Node'; import { clamp } from 'lodash-es'; @@ -200,106 +199,101 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => { if (color) { manager.stateApi.setFill(color); } - } + manager.preview.tool.render(); + } else { + const isDrawable = selectedEntity?.state.isEnabled; + if (pos && isDrawable && !$spaceKey.get() && getIsPrimaryMouseDown(e)) { + $lastMouseDownPos.set(pos); + const normalizedPoint = offsetCoord(pos, selectedEntity.state.position); - if ( - pos && - selectedEntity && - isDrawableEntity(selectedEntity.state) && - !$spaceKey.get() && - getIsPrimaryMouseDown(e) - ) { - $lastMouseDownPos.set(pos); - const normalizedPoint = offsetCoord(pos, selectedEntity.state.position); + if (toolState.selected === 'brush') { + const lastLinePoint = getLastPointOfLastLineOfEntity(selectedEntity.state, toolState.selected); + const alignedPoint = alignCoordForTool(normalizedPoint, toolState.brush.width); + if (e.evt.shiftKey && lastLinePoint) { + // Create a straight line from the last line point + if (selectedEntity.adapter.renderer.bufferState) { + selectedEntity.adapter.renderer.commitBuffer(); + } - if (toolState.selected === 'brush') { - const lastLinePoint = getLastPointOfLastLineOfEntity(selectedEntity.state, toolState.selected); - const alignedPoint = alignCoordForTool(normalizedPoint, toolState.brush.width); - if (e.evt.shiftKey && lastLinePoint) { - // Create a straight line from the last line point + await selectedEntity.adapter.renderer.setBuffer({ + id: getObjectId('brush_line', true), + type: 'brush_line', + points: [ + // The last point of the last line is already normalized to the entity's coordinates + lastLinePoint.x, + lastLinePoint.y, + alignedPoint.x, + alignedPoint.y, + ], + strokeWidth: toolState.brush.width, + color: getCurrentFill(), + clip: getClip(selectedEntity.state), + }); + } else { + if (selectedEntity.adapter.renderer.bufferState) { + selectedEntity.adapter.renderer.commitBuffer(); + } + await selectedEntity.adapter.renderer.setBuffer({ + id: getObjectId('brush_line', true), + type: 'brush_line', + points: [alignedPoint.x, alignedPoint.y], + strokeWidth: toolState.brush.width, + color: getCurrentFill(), + clip: getClip(selectedEntity.state), + }); + } + $lastAddedPoint.set(alignedPoint); + } + + if (toolState.selected === 'eraser') { + const lastLinePoint = getLastPointOfLastLineOfEntity(selectedEntity.state, toolState.selected); + const alignedPoint = alignCoordForTool(normalizedPoint, toolState.eraser.width); + if (e.evt.shiftKey && lastLinePoint) { + // Create a straight line from the last line point + if (selectedEntity.adapter.renderer.bufferState) { + selectedEntity.adapter.renderer.commitBuffer(); + } + await selectedEntity.adapter.renderer.setBuffer({ + id: getObjectId('eraser_line', true), + type: 'eraser_line', + points: [ + // The last point of the last line is already normalized to the entity's coordinates + lastLinePoint.x, + lastLinePoint.y, + alignedPoint.x, + alignedPoint.y, + ], + strokeWidth: toolState.eraser.width, + clip: getClip(selectedEntity.state), + }); + } else { + if (selectedEntity.adapter.renderer.bufferState) { + selectedEntity.adapter.renderer.commitBuffer(); + } + await selectedEntity.adapter.renderer.setBuffer({ + id: getObjectId('eraser_line', true), + type: 'eraser_line', + points: [alignedPoint.x, alignedPoint.y], + strokeWidth: toolState.eraser.width, + clip: getClip(selectedEntity.state), + }); + } + $lastAddedPoint.set(alignedPoint); + } + + if (toolState.selected === 'rect') { if (selectedEntity.adapter.renderer.bufferState) { selectedEntity.adapter.renderer.commitBuffer(); } - await selectedEntity.adapter.renderer.setBuffer({ - id: getObjectId('brush_line', true), - type: 'brush_line', - points: [ - // The last point of the last line is already normalized to the entity's coordinates - lastLinePoint.x, - lastLinePoint.y, - alignedPoint.x, - alignedPoint.y, - ], - strokeWidth: toolState.brush.width, + id: getObjectId('rect', true), + type: 'rect', + rect: { x: Math.round(normalizedPoint.x), y: Math.round(normalizedPoint.y), width: 0, height: 0 }, color: getCurrentFill(), - clip: getClip(selectedEntity.state), - }); - } else { - if (selectedEntity.adapter.renderer.bufferState) { - selectedEntity.adapter.renderer.commitBuffer(); - } - await selectedEntity.adapter.renderer.setBuffer({ - id: getObjectId('brush_line', true), - type: 'brush_line', - points: [alignedPoint.x, alignedPoint.y], - strokeWidth: toolState.brush.width, - color: getCurrentFill(), - clip: getClip(selectedEntity.state), }); } - $lastAddedPoint.set(alignedPoint); - } - - if (toolState.selected === 'eraser') { - const lastLinePoint = getLastPointOfLastLineOfEntity(selectedEntity.state, toolState.selected); - const alignedPoint = alignCoordForTool(normalizedPoint, toolState.eraser.width); - if (e.evt.shiftKey && lastLinePoint) { - // Create a straight line from the last line point - if (selectedEntity.adapter.renderer.bufferState) { - selectedEntity.adapter.renderer.commitBuffer(); - } - await selectedEntity.adapter.renderer.setBuffer({ - id: getObjectId('eraser_line', true), - type: 'eraser_line', - points: [ - // The last point of the last line is already normalized to the entity's coordinates - lastLinePoint.x, - lastLinePoint.y, - alignedPoint.x, - alignedPoint.y, - ], - strokeWidth: toolState.eraser.width, - clip: getClip(selectedEntity.state), - }); - } else { - if (selectedEntity.adapter.renderer.bufferState) { - selectedEntity.adapter.renderer.commitBuffer(); - } - await selectedEntity.adapter.renderer.setBuffer({ - id: getObjectId('eraser_line', true), - type: 'eraser_line', - points: [alignedPoint.x, alignedPoint.y], - strokeWidth: toolState.eraser.width, - clip: getClip(selectedEntity.state), - }); - } - $lastAddedPoint.set(alignedPoint); - } - - if (toolState.selected === 'rect') { - if (selectedEntity.adapter.renderer.bufferState) { - selectedEntity.adapter.renderer.commitBuffer(); - } - await selectedEntity.adapter.renderer.setBuffer({ - id: getObjectId('rect', true), - type: 'rect', - rect: { x: Math.round(normalizedPoint.x), y: Math.round(normalizedPoint.y), width: 0, height: 0 }, - color: getCurrentFill(), - }); } } - manager.preview.tool.render(); }); //#region mouseup @@ -307,8 +301,8 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => { $isMouseDown.set(false); const pos = $lastCursorPos.get(); const selectedEntity = getSelectedEntity(); - - if (pos && selectedEntity && isDrawableEntity(selectedEntity.state) && !$spaceKey.get()) { + const isDrawable = selectedEntity?.state.isEnabled; + if (pos && isDrawable && !$spaceKey.get()) { const toolState = getToolState(); if (toolState.selected === 'brush') { @@ -340,7 +334,6 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => { $lastMouseDownPos.set(null); } - manager.preview.tool.render(); }); @@ -353,104 +346,98 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => { if (toolState.selected === 'eyeDropper') { const color = getColorUnderCursor(stage); manager.stateApi.$colorUnderCursor.set(color); - } - - if ( - pos && - selectedEntity && - isDrawableEntity(selectedEntity.state) && - selectedEntity.adapter && - isDrawableEntityAdapter(selectedEntity.adapter) && - !$spaceKey.get() && - getIsPrimaryMouseDown(e) - ) { - if (toolState.selected === 'brush') { - const drawingBuffer = selectedEntity.adapter.renderer.bufferState; - if (drawingBuffer) { - if (drawingBuffer.type === 'brush_line') { - const lastPoint = getLastPointOfLine(drawingBuffer.points); - const nextPoint = getNextPoint(pos, toolState, lastPoint); - if (lastPoint && nextPoint) { - const normalizedPoint = offsetCoord(nextPoint, selectedEntity.state.position); - const alignedPoint = alignCoordForTool(normalizedPoint, toolState.brush.width); - // Do not add duplicate points - if (lastPoint.x !== alignedPoint.x || lastPoint.y !== alignedPoint.y) { - drawingBuffer.points.push(alignedPoint.x, alignedPoint.y); - await selectedEntity.adapter.renderer.setBuffer(drawingBuffer); - $lastAddedPoint.set(alignedPoint); + } else { + const isDrawable = selectedEntity?.state.isEnabled; + if (pos && isDrawable && !$spaceKey.get() && getIsPrimaryMouseDown(e)) { + if (toolState.selected === 'brush') { + const drawingBuffer = selectedEntity.adapter.renderer.bufferState; + if (drawingBuffer) { + if (drawingBuffer.type === 'brush_line') { + const lastPoint = getLastPointOfLine(drawingBuffer.points); + const nextPoint = getNextPoint(pos, toolState, lastPoint); + if (lastPoint && nextPoint) { + const normalizedPoint = offsetCoord(nextPoint, selectedEntity.state.position); + const alignedPoint = alignCoordForTool(normalizedPoint, toolState.brush.width); + // Do not add duplicate points + if (lastPoint.x !== alignedPoint.x || lastPoint.y !== alignedPoint.y) { + drawingBuffer.points.push(alignedPoint.x, alignedPoint.y); + await selectedEntity.adapter.renderer.setBuffer(drawingBuffer); + $lastAddedPoint.set(alignedPoint); + } } + } else { + selectedEntity.adapter.renderer.clearBuffer(); } } else { - selectedEntity.adapter.renderer.clearBuffer(); - } - } else { - if (selectedEntity.adapter.renderer.bufferState) { - selectedEntity.adapter.renderer.commitBuffer(); - } - const normalizedPoint = offsetCoord(pos, selectedEntity.state.position); - const alignedPoint = alignCoordForTool(normalizedPoint, toolState.brush.width); - await selectedEntity.adapter.renderer.setBuffer({ - id: getObjectId('brush_line', true), - type: 'brush_line', - points: [alignedPoint.x, alignedPoint.y], - strokeWidth: toolState.brush.width, - color: getCurrentFill(), - clip: getClip(selectedEntity.state), - }); - $lastAddedPoint.set(alignedPoint); - } - } - - if (toolState.selected === 'eraser') { - const drawingBuffer = selectedEntity.adapter.renderer.bufferState; - if (drawingBuffer) { - if (drawingBuffer.type === 'eraser_line') { - const lastPoint = getLastPointOfLine(drawingBuffer.points); - const nextPoint = getNextPoint(pos, toolState, lastPoint); - if (lastPoint && nextPoint) { - const normalizedPoint = offsetCoord(nextPoint, selectedEntity.state.position); - const alignedPoint = alignCoordForTool(normalizedPoint, toolState.eraser.width); - // Do not add duplicate points - if (lastPoint.x !== alignedPoint.x || lastPoint.y !== alignedPoint.y) { - drawingBuffer.points.push(alignedPoint.x, alignedPoint.y); - await selectedEntity.adapter.renderer.setBuffer(drawingBuffer); - $lastAddedPoint.set(alignedPoint); - } + if (selectedEntity.adapter.renderer.bufferState) { + selectedEntity.adapter.renderer.commitBuffer(); } - } else { - selectedEntity.adapter.renderer.clearBuffer(); - } - } else { - if (selectedEntity.adapter.renderer.bufferState) { - selectedEntity.adapter.renderer.commitBuffer(); - } - const normalizedPoint = offsetCoord(pos, selectedEntity.state.position); - const alignedPoint = alignCoordForTool(normalizedPoint, toolState.eraser.width); - await selectedEntity.adapter.renderer.setBuffer({ - id: getObjectId('eraser_line', true), - type: 'eraser_line', - points: [alignedPoint.x, alignedPoint.y], - strokeWidth: toolState.eraser.width, - clip: getClip(selectedEntity.state), - }); - $lastAddedPoint.set(alignedPoint); - } - } - - if (toolState.selected === 'rect') { - const drawingBuffer = selectedEntity.adapter.renderer.bufferState; - if (drawingBuffer) { - if (drawingBuffer.type === 'rect') { const normalizedPoint = offsetCoord(pos, selectedEntity.state.position); - drawingBuffer.rect.width = Math.round(normalizedPoint.x - drawingBuffer.rect.x); - drawingBuffer.rect.height = Math.round(normalizedPoint.y - drawingBuffer.rect.y); - await selectedEntity.adapter.renderer.setBuffer(drawingBuffer); + const alignedPoint = alignCoordForTool(normalizedPoint, toolState.brush.width); + await selectedEntity.adapter.renderer.setBuffer({ + id: getObjectId('brush_line', true), + type: 'brush_line', + points: [alignedPoint.x, alignedPoint.y], + strokeWidth: toolState.brush.width, + color: getCurrentFill(), + clip: getClip(selectedEntity.state), + }); + $lastAddedPoint.set(alignedPoint); + } + } + + if (toolState.selected === 'eraser') { + const drawingBuffer = selectedEntity.adapter.renderer.bufferState; + if (drawingBuffer) { + if (drawingBuffer.type === 'eraser_line') { + const lastPoint = getLastPointOfLine(drawingBuffer.points); + const nextPoint = getNextPoint(pos, toolState, lastPoint); + if (lastPoint && nextPoint) { + const normalizedPoint = offsetCoord(nextPoint, selectedEntity.state.position); + const alignedPoint = alignCoordForTool(normalizedPoint, toolState.eraser.width); + // Do not add duplicate points + if (lastPoint.x !== alignedPoint.x || lastPoint.y !== alignedPoint.y) { + drawingBuffer.points.push(alignedPoint.x, alignedPoint.y); + await selectedEntity.adapter.renderer.setBuffer(drawingBuffer); + $lastAddedPoint.set(alignedPoint); + } + } + } else { + selectedEntity.adapter.renderer.clearBuffer(); + } } else { - selectedEntity.adapter.renderer.clearBuffer(); + if (selectedEntity.adapter.renderer.bufferState) { + selectedEntity.adapter.renderer.commitBuffer(); + } + const normalizedPoint = offsetCoord(pos, selectedEntity.state.position); + const alignedPoint = alignCoordForTool(normalizedPoint, toolState.eraser.width); + await selectedEntity.adapter.renderer.setBuffer({ + id: getObjectId('eraser_line', true), + type: 'eraser_line', + points: [alignedPoint.x, alignedPoint.y], + strokeWidth: toolState.eraser.width, + clip: getClip(selectedEntity.state), + }); + $lastAddedPoint.set(alignedPoint); + } + } + + if (toolState.selected === 'rect') { + const drawingBuffer = selectedEntity.adapter.renderer.bufferState; + if (drawingBuffer) { + if (drawingBuffer.type === 'rect') { + const normalizedPoint = offsetCoord(pos, selectedEntity.state.position); + drawingBuffer.rect.width = Math.round(normalizedPoint.x - drawingBuffer.rect.x); + drawingBuffer.rect.height = Math.round(normalizedPoint.y - drawingBuffer.rect.y); + await selectedEntity.adapter.renderer.setBuffer(drawingBuffer); + } else { + selectedEntity.adapter.renderer.clearBuffer(); + } } } } } + manager.preview.tool.render(); }); @@ -461,14 +448,9 @@ export const setStageEventHandlers = (manager: CanvasManager): (() => void) => { $lastMouseDownPos.set(null); const selectedEntity = getSelectedEntity(); const toolState = getToolState(); + const isDrawable = selectedEntity?.state.isEnabled; - if ( - pos && - selectedEntity && - isDrawableEntity(selectedEntity.state) && - !$spaceKey.get() && - getIsPrimaryMouseDown(e) - ) { + if (pos && isDrawable && !$spaceKey.get() && getIsPrimaryMouseDown(e)) { const drawingBuffer = selectedEntity.adapter.renderer.bufferState; const normalizedPoint = offsetCoord(pos, selectedEntity.state.position); if (toolState.selected === 'brush' && drawingBuffer?.type === 'brush_line') {