fix(ui): edge cases with tool rendering

This commit is contained in:
psychedelicious
2024-10-02 15:42:14 +10:00
committed by Kent Keirsey
parent c4421241f6
commit 324a46d0c8
4 changed files with 82 additions and 50 deletions

View File

@@ -91,15 +91,32 @@ export class CanvasToolBrush extends CanvasModuleBase {
};
this.konva.group.add(this.konva.fillCircle, this.konva.innerBorder, this.konva.outerBorder);
}
render = () => {
const cursorPos = this.manager.tool.$cursorPos.get();
const tool = this.parent.$tool.get();
// If the cursor position is not available, do not update the brush preview. The tool module will handle visiblity.
if (!cursorPos) {
if (tool !== 'brush') {
this.setVisibility(false);
return;
}
const cursorPos = this.parent.$cursorPos.get();
const canDraw = this.parent.getCanDraw();
if (!cursorPos || !canDraw) {
this.setVisibility(false);
return;
}
const isMouseDown = this.parent.$isMouseDown.get();
const lastPointerType = this.parent.$lastPointerType.get();
if (lastPointerType !== 'mouse' && isMouseDown) {
this.setVisibility(false);
return;
}
this.setVisibility(true);
if (this.hideFillTimeoutId !== null) {
window.clearTimeout(this.hideFillTimeoutId);
this.hideFillTimeoutId = null;
@@ -116,7 +133,7 @@ export class CanvasToolBrush extends CanvasModuleBase {
y: alignedCursorPos.y,
radius,
fill: rgbaColorToString(brushPreviewFill),
visible: !this.manager.tool.$isMouseDown.get(),
visible: !isMouseDown && lastPointerType === 'mouse',
});
// But the borders are in screen-pixels

View File

@@ -190,13 +190,31 @@ export class CanvasToolColorPicker extends CanvasModuleBase {
* Renders the color picker tool preview on the canvas.
*/
render = () => {
const cursorPos = this.manager.tool.$cursorPos.get();
const tool = this.parent.$tool.get();
// If the cursor position is not available, do not render the preview. The tool module will handle visibility.
if (!cursorPos) {
if (tool !== 'colorPicker') {
this.setVisibility(false);
return;
}
const cursorPos = this.parent.$cursorPos.get();
const canDraw = this.parent.getCanDraw();
if (!cursorPos || tool !== 'colorPicker' || !canDraw) {
this.setVisibility(false);
return;
}
const isMouseDown = this.parent.$isMouseDown.get();
const lastPointerType = this.parent.$lastPointerType.get();
if (lastPointerType !== 'mouse' && !isMouseDown) {
this.setVisibility(false);
return;
}
this.setVisibility(true);
const settings = this.manager.stateApi.getSettings();
const colorUnderCursor = this.parent.$colorUnderCursor.get();
const colorPickerInnerRadius = this.manager.stage.unscale(this.config.RING_INNER_RADIUS);

View File

@@ -78,12 +78,31 @@ export class CanvasToolEraser extends CanvasModuleBase {
}
render = () => {
const cursorPos = this.manager.tool.$cursorPos.get();
const tool = this.parent.$tool.get();
if (!cursorPos) {
if (tool !== 'eraser') {
this.setVisibility(false);
return;
}
const cursorPos = this.parent.$cursorPos.get();
const canDraw = this.parent.getCanDraw();
if (!cursorPos || !canDraw) {
this.setVisibility(false);
return;
}
const isMouseDown = this.parent.$isMouseDown.get();
const lastPointerType = this.parent.$lastPointerType.get();
if (lastPointerType !== 'mouse' && isMouseDown) {
this.setVisibility(false);
return;
}
this.setVisibility(true);
const settings = this.manager.stateApi.getSettings();
const alignedCursorPos = alignCoordForTool(cursorPos, settings.eraserWidth);
const radius = settings.eraserWidth / 2;

View File

@@ -27,7 +27,7 @@ import type {
RgbColor,
Tool,
} from 'features/controlLayers/store/types';
import { isRenderableEntity, RGBA_BLACK } from 'features/controlLayers/store/types';
import { RGBA_BLACK } from 'features/controlLayers/store/types';
import Konva from 'konva';
import type { KonvaEventObject } from 'konva/lib/Node';
import { atom } from 'nanostores';
@@ -171,41 +171,23 @@ export class CanvasToolModule extends CanvasModuleBase {
};
render = () => {
const stage = this.manager.stage;
const renderedEntityCount = this.manager.stateApi.getRenderedEntityCount();
const selectedEntity = this.manager.stateApi.getSelectedEntityAdapter();
const cursorPos = this.$cursorPos.get();
const tool = this.$tool.get();
const isFiltering = this.manager.stateApi.$isFiltering.get();
const isStaging = this.manager.stagingArea.$isStaging.get();
const lastPointerType = this.$lastPointerType.get();
const isDrawable =
!!selectedEntity &&
selectedEntity.state.isEnabled &&
!selectedEntity.state.isLocked &&
isRenderableEntity(selectedEntity.state);
this.syncCursorStyle();
stage.setIsDraggable(tool === 'view');
this.manager.stage.setIsDraggable(tool === 'view');
if (!cursorPos || lastPointerType !== 'mouse' || renderedEntityCount === 0 || isFiltering || isStaging) {
// We can bail early if the mouse isn't over the stage or there are no layers
if (!cursorPos || isFiltering || isStaging || renderedEntityCount === 0) {
this.konva.group.visible(false);
} else {
this.konva.group.visible(true);
// No need to render the brush preview if the cursor position or color is missing
if (cursorPos && tool === 'brush') {
this.brushToolPreview.render();
} else if (cursorPos && tool === 'eraser') {
this.eraserToolPreview.render();
} else if (cursorPos && tool === 'colorPicker') {
this.colorPickerToolPreview.render();
}
this.setToolVisibility(tool, isDrawable);
this.brushToolPreview.render();
this.eraserToolPreview.render();
this.colorPickerToolPreview.render();
}
};
@@ -398,14 +380,6 @@ export class CanvasToolModule extends CanvasModuleBase {
const tool = this.$tool.get();
const settings = this.manager.stateApi.getSettings();
if (tool === 'colorPicker') {
const color = this.getColorUnderCursor();
if (color) {
this.manager.stateApi.setColor({ ...settings.color, ...color });
}
return;
}
const isMouseDown = this.$isMouseDown.get();
const selectedEntity = this.manager.stateApi.getSelectedEntityAdapter();
@@ -555,12 +529,22 @@ export class CanvasToolModule extends CanvasModuleBase {
return;
}
const tool = this.$tool.get();
const settings = this.manager.stateApi.getSettings();
if (tool === 'colorPicker') {
const color = this.getColorUnderCursor();
if (color) {
this.manager.stateApi.setColor({ ...settings.color, ...color });
}
return;
}
const selectedEntity = this.manager.stateApi.getSelectedEntityAdapter();
const isDrawable = selectedEntity?.state.isEnabled && !selectedEntity.state.isLocked;
if (!isDrawable) {
return;
}
const tool = this.$tool.get();
if (tool === 'brush') {
if (
@@ -754,14 +738,8 @@ export class CanvasToolModule extends CanvasModuleBase {
* whatever the user was drawing from being lost, or ending up with stale state, we need to commit the buffer
* on window pointer up.
*/
onWindowPointerUp = (e: PointerEvent) => {
onWindowPointerUp = (_: PointerEvent) => {
try {
this.$lastPointerType.set(e.pointerType);
if (e.pointerType !== 'mouse') {
this.$cursorPos.set(null);
}
this.$isMouseDown.set(false);
const selectedEntity = this.manager.stateApi.getSelectedEntityAdapter();