From b3f6edc323998e6e11fdd62396fe39603b8af6c6 Mon Sep 17 00:00:00 2001 From: Hikaru Y Date: Tue, 10 Oct 2023 12:51:35 +0900 Subject: [PATCH] Fix polygon tool not working (#2712) * Fix polygon not converting correctly to cloze * Fix first polygon disappearing when creating se... ...cond one during editing Previously, a fabric object was passed directly to a `Shape` such as `Rectangle` or `Polygon`, so mutating a non-primitive property of the shape would lead to mutating the original fabric object as well. * Commit addition of polygon immediately Unlike the rect or ellipse tools, when the polygon tool was active, clicking on the canvas did not fire the `object:removed` event and the `change` event was not dispatched. As a result, an addition of a polygon was not saved to the DB when switching to another note or closing the editor in edit mode without performing an action that dispatched the `change` event. --- ts/image-occlusion/shapes/to-cloze.ts | 13 +++++++++---- ts/image-occlusion/tools/tool-polygon.ts | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ts/image-occlusion/shapes/to-cloze.ts b/ts/image-occlusion/shapes/to-cloze.ts index f6f59689a..96f4db274 100644 --- a/ts/image-occlusion/shapes/to-cloze.ts +++ b/ts/image-occlusion/shapes/to-cloze.ts @@ -3,6 +3,7 @@ import type { Canvas, Object as FabricObject } from "fabric"; import { fabric } from "fabric"; +import { cloneDeep } from "lodash-es"; import { makeMaskTransparent } from "../tools/lib"; import type { Size } from "../types"; @@ -52,15 +53,19 @@ function fabricObjectToBaseShapeOrShapes( ): ShapeOrShapes | null { let shape: Shape; + // Prevents the original fabric object from mutating when a non-primitive + // property of a Shape mutates. + const cloned = cloneDeep(object); + switch (object.type) { case "rect": - shape = new Rectangle(object); + shape = new Rectangle(cloned); break; case "ellipse": - shape = new Ellipse(object); + shape = new Ellipse(cloned); break; case "polygon": - shape = new Polygon(object); + shape = new Polygon(cloned); break; case "group": return object._objects.map((child) => { @@ -96,7 +101,7 @@ function shapeOrShapesToCloze( ): string { let text = ""; function addKeyValue(key: string, value: string) { - if (Number.isNaN(Number(value))) { + if (key !== "points" && Number.isNaN(Number(value))) { value = ".0000"; } text += `:${key}=${value}`; diff --git a/ts/image-occlusion/tools/tool-polygon.ts b/ts/image-occlusion/tools/tool-polygon.ts index dd32cf8c0..a57894f11 100644 --- a/ts/image-occlusion/tools/tool-polygon.ts +++ b/ts/image-occlusion/tools/tool-polygon.ts @@ -4,6 +4,7 @@ import { fabric } from "fabric"; import type { PanZoom } from "panzoom"; +import { emitChangeSignal } from "../MaskEditor.svelte"; import { BORDER_COLOR, disableRotation, SHAPE_MASK_COLOR } from "./lib"; import { undoStack } from "./tool-undo-redo"; @@ -190,6 +191,7 @@ const generatePolygon = (canvas: fabric.Canvas, pointsList): void => { canvas.add(polygon); // view undo redo tools undoStack.onObjectAdded(polygon.id); + emitChangeSignal(); } polygon.on("modified", () => {