From b09f9789de7922699e4222225ffa13e2557bf326 Mon Sep 17 00:00:00 2001 From: Dariusz L Date: Wed, 30 Jul 2025 10:37:12 +0200 Subject: [PATCH] Last Point yellow Added a clear first point distinction when drawing a custom shape: if the mouse cursor is near the beginning of a line (the shape can be closed), the first point is drawn in yellow and larger. This allows the user to see when they can close the shape with a single click. The code has been compiled and is ready to use. The functionality works as expected. --- js/BatchPreviewManager.js | 8 +++++--- js/CanvasInteractions.js | 4 ++++ js/ShapeTool.js | 21 +++++++++++++++++++-- src/BatchPreviewManager.ts | 13 +++++++------ src/CanvasInteractions.ts | 5 +++++ src/ShapeTool.ts | 21 +++++++++++++++++++-- 6 files changed, 59 insertions(+), 13 deletions(-) diff --git a/js/BatchPreviewManager.js b/js/BatchPreviewManager.js index 19f49a6..d6fb68a 100644 --- a/js/BatchPreviewManager.js +++ b/js/BatchPreviewManager.js @@ -179,8 +179,6 @@ export class BatchPreviewManager { this.layers.forEach((layer) => { layer.visible = true; }); - // Clear selection - deselect all layers - this.canvas.updateSelection([]); // Update the layers panel to reflect visibility changes if (this.canvas.canvasLayersPanel) { this.canvas.canvasLayersPanel.onLayersChanged(); @@ -229,7 +227,11 @@ export class BatchPreviewManager { }); // Show only the current layer layer.visible = true; - this.canvas.updateSelection([layer]); + // Deselect only this layer if it is selected + const selected = this.canvas.canvasSelection.selectedLayers; + if (selected && selected.includes(layer)) { + this.canvas.updateSelection(selected.filter((l) => l !== layer)); + } // Update the layers panel to reflect visibility changes if (this.canvas.canvasLayersPanel) { this.canvas.canvasLayersPanel.onLayersChanged(); diff --git a/js/CanvasInteractions.js b/js/CanvasInteractions.js index ddc0b11..54a3b68 100644 --- a/js/CanvasInteractions.js +++ b/js/CanvasInteractions.js @@ -198,6 +198,10 @@ export class CanvasInteractions { this.updateCursor(coords.world); break; } + // --- DYNAMICZNY PODGLĄD LINII CUSTOM SHAPE --- + if (this.canvas.shapeTool.isActive && !this.canvas.shapeTool.shape.isClosed) { + this.canvas.render(); + } } handleMouseUp(e) { const coords = this.getMouseCoordinates(e); diff --git a/js/ShapeTool.js b/js/ShapeTool.js index 591ead9..05c7960 100644 --- a/js/ShapeTool.js +++ b/js/ShapeTool.js @@ -114,10 +114,27 @@ export class ShapeTool { } ctx.stroke(); // Draw vertices - ctx.fillStyle = 'rgba(0, 255, 255, 1)'; + const mouse = this.canvas.lastMousePosition; + const firstPoint = this.shape.points[0]; + let highlightFirst = false; + if (!this.shape.isClosed && this.shape.points.length > 2 && mouse) { + const dx = mouse.x - firstPoint.x; + const dy = mouse.y - firstPoint.y; + const dist = Math.sqrt(dx * dx + dy * dy); + if (dist < 10 / this.canvas.viewport.zoom) { + highlightFirst = true; + } + } this.shape.points.forEach((point, index) => { ctx.beginPath(); - ctx.arc(point.x, point.y, 4 / this.canvas.viewport.zoom, 0, 2 * Math.PI); + if (index === 0 && highlightFirst) { + ctx.arc(point.x, point.y, 8 / this.canvas.viewport.zoom, 0, 2 * Math.PI); + ctx.fillStyle = 'yellow'; + } + else { + ctx.arc(point.x, point.y, 4 / this.canvas.viewport.zoom, 0, 2 * Math.PI); + ctx.fillStyle = 'rgba(0, 255, 255, 1)'; + } ctx.fill(); }); ctx.restore(); diff --git a/src/BatchPreviewManager.ts b/src/BatchPreviewManager.ts index ed7cf14..0de5267 100644 --- a/src/BatchPreviewManager.ts +++ b/src/BatchPreviewManager.ts @@ -234,9 +234,6 @@ export class BatchPreviewManager { layer.visible = true; }); - // Clear selection - deselect all layers - this.canvas.updateSelection([]); - // Update the layers panel to reflect visibility changes if (this.canvas.canvasLayersPanel) { this.canvas.canvasLayersPanel.onLayersChanged(); @@ -296,9 +293,13 @@ export class BatchPreviewManager { // Show only the current layer layer.visible = true; - - this.canvas.updateSelection([layer]); - + + // Deselect only this layer if it is selected + const selected = this.canvas.canvasSelection.selectedLayers; + if (selected && selected.includes(layer)) { + this.canvas.updateSelection(selected.filter((l: Layer) => l !== layer)); + } + // Update the layers panel to reflect visibility changes if (this.canvas.canvasLayersPanel) { this.canvas.canvasLayersPanel.onLayersChanged(); diff --git a/src/CanvasInteractions.ts b/src/CanvasInteractions.ts index 79f7e51..8aef7ba 100644 --- a/src/CanvasInteractions.ts +++ b/src/CanvasInteractions.ts @@ -258,6 +258,11 @@ export class CanvasInteractions { this.updateCursor(coords.world); break; } + + // --- DYNAMICZNY PODGLĄD LINII CUSTOM SHAPE --- + if (this.canvas.shapeTool.isActive && !this.canvas.shapeTool.shape.isClosed) { + this.canvas.render(); + } } handleMouseUp(e: MouseEvent): void { diff --git a/src/ShapeTool.ts b/src/ShapeTool.ts index 18cc7e0..aefe614 100644 --- a/src/ShapeTool.ts +++ b/src/ShapeTool.ts @@ -143,10 +143,27 @@ export class ShapeTool { ctx.stroke(); // Draw vertices - ctx.fillStyle = 'rgba(0, 255, 255, 1)'; + const mouse = this.canvas.lastMousePosition; + const firstPoint = this.shape.points[0]; + let highlightFirst = false; + if (!this.shape.isClosed && this.shape.points.length > 2 && mouse) { + const dx = mouse.x - firstPoint.x; + const dy = mouse.y - firstPoint.y; + const dist = Math.sqrt(dx * dx + dy * dy); + if (dist < 10 / this.canvas.viewport.zoom) { + highlightFirst = true; + } + } + this.shape.points.forEach((point, index) => { ctx.beginPath(); - ctx.arc(point.x, point.y, 4 / this.canvas.viewport.zoom, 0, 2 * Math.PI); + if (index === 0 && highlightFirst) { + ctx.arc(point.x, point.y, 8 / this.canvas.viewport.zoom, 0, 2 * Math.PI); + ctx.fillStyle = 'yellow'; + } else { + ctx.arc(point.x, point.y, 4 / this.canvas.viewport.zoom, 0, 2 * Math.PI); + ctx.fillStyle = 'rgba(0, 255, 255, 1)'; + } ctx.fill(); });