break polygon on restore/finalize if invalid & prevent creation
This commit is contained in:
parent
ad1c28c27c
commit
d56bb4087f
@ -1290,16 +1290,17 @@ export class LinearElementEditor {
|
||||
app.state.editingLinearElement?.lastUncommittedPoint ===
|
||||
element.points[element.points.length - 1];
|
||||
|
||||
const isPolygon = isLineElement(element) && element.polygon;
|
||||
|
||||
// break polygon if deleting start/end point
|
||||
if (isLineElement(element) && element.polygon) {
|
||||
if (
|
||||
pointIndices.includes(0) ||
|
||||
(pointIndices.includes(element.points.length - 1) &&
|
||||
// don't disable polygon if cleaning up uncommitted point
|
||||
!isUncommittedPoint)
|
||||
) {
|
||||
app.scene.mutateElement(element, { polygon: false });
|
||||
}
|
||||
if (
|
||||
isPolygon &&
|
||||
// don't disable polygon if cleaning up uncommitted point
|
||||
!isUncommittedPoint &&
|
||||
(pointIndices.includes(0) ||
|
||||
pointIndices.includes(element.points.length - 1))
|
||||
) {
|
||||
app.scene.mutateElement(element, { polygon: false });
|
||||
}
|
||||
|
||||
const nextPoints = element.points.filter((_, idx) => {
|
||||
|
@ -36,6 +36,8 @@ import { ShapeCache } from "./ShapeCache";
|
||||
|
||||
import { getElementAbsoluteCoords, type Bounds } from "./bounds";
|
||||
|
||||
import { canBecomePolygon } from "./typeChecks";
|
||||
|
||||
import type {
|
||||
ElementsMap,
|
||||
ExcalidrawElement,
|
||||
@ -402,10 +404,17 @@ export const isPathALoop = (
|
||||
export const toggleLinePolygonState = (
|
||||
element: ExcalidrawLineElement,
|
||||
nextPolygonState: boolean,
|
||||
) => {
|
||||
): {
|
||||
polygon: ExcalidrawLineElement["polygon"];
|
||||
points: ExcalidrawLineElement["points"];
|
||||
} | null => {
|
||||
const updatedPoints = [...element.points];
|
||||
|
||||
if (nextPolygonState) {
|
||||
if (!canBecomePolygon(element.points)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const firstPoint = updatedPoints[0];
|
||||
const lastPoint = updatedPoints[updatedPoints.length - 1];
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { ROUNDNESS, assertNever } from "@excalidraw/common";
|
||||
|
||||
import { pointsEqual } from "@excalidraw/math";
|
||||
|
||||
import type { ElementOrToolType } from "@excalidraw/excalidraw/types";
|
||||
|
||||
import type { MarkNonNullable } from "@excalidraw/common/utility-types";
|
||||
@ -379,3 +381,26 @@ export const getLinearElementSubType = (
|
||||
}
|
||||
return "line";
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if current element points meet all the conditions for polygon=true
|
||||
* (this isn't a element type check, for that use isLineElement).
|
||||
*
|
||||
* If you want to check if points *can* be turned into a polygon, use
|
||||
* canBecomePolygon(points).
|
||||
*/
|
||||
export const isValidPolygon = (
|
||||
points: ExcalidrawLineElement["points"],
|
||||
): boolean => {
|
||||
return points.length > 3 && pointsEqual(points[0], points[points.length - 1]);
|
||||
};
|
||||
|
||||
export const canBecomePolygon = (
|
||||
points: ExcalidrawLineElement["points"],
|
||||
): boolean => {
|
||||
return (
|
||||
points.length > 3 ||
|
||||
// 3-point polygons can't have all points in a single line
|
||||
(points.length === 3 && !pointsEqual(points[0], points[points.length - 1]))
|
||||
);
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ import {
|
||||
bindOrUnbindLinearElement,
|
||||
isBindingEnabled,
|
||||
} from "@excalidraw/element/binding";
|
||||
import { LinearElementEditor } from "@excalidraw/element/linearElementEditor";
|
||||
import { isValidPolygon, LinearElementEditor } from "@excalidraw/element";
|
||||
|
||||
import {
|
||||
isBindingElement,
|
||||
@ -99,6 +99,12 @@ export const actionFinalize = register({
|
||||
scene,
|
||||
);
|
||||
}
|
||||
if (isLineElement(element) && !isValidPolygon(element.points)) {
|
||||
scene.mutateElement(element, {
|
||||
polygon: false,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
elements:
|
||||
element.points.length < 2 || isInvisiblySmallElement(element)
|
||||
@ -198,6 +204,12 @@ export const actionFinalize = register({
|
||||
}
|
||||
}
|
||||
|
||||
if (isLineElement(element) && !isValidPolygon(element.points)) {
|
||||
scene.mutateElement(element, {
|
||||
polygon: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
isBindingElement(element) &&
|
||||
!isLoop &&
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
reduceToCommonValue,
|
||||
} from "@excalidraw/common";
|
||||
|
||||
import { getNonDeletedElements } from "@excalidraw/element";
|
||||
import { canBecomePolygon, getNonDeletedElements } from "@excalidraw/element";
|
||||
|
||||
import {
|
||||
bindLinearElement,
|
||||
@ -364,18 +364,16 @@ export const actionChangeBackgroundColor = register({
|
||||
};
|
||||
}
|
||||
|
||||
const selectedElements = app.scene.getSelectedElements(appState);
|
||||
const shouldEnablePolygon = selectedElements.every((el) =>
|
||||
isLineElement(el),
|
||||
);
|
||||
|
||||
let nextElements;
|
||||
|
||||
if (
|
||||
shouldEnablePolygon &&
|
||||
value.currentItemBackgroundColor &&
|
||||
!isTransparent(value.currentItemBackgroundColor)
|
||||
) {
|
||||
const selectedElements = app.scene.getSelectedElements(appState);
|
||||
const shouldEnablePolygon =
|
||||
!isTransparent(value.currentItemBackgroundColor) &&
|
||||
selectedElements.every(
|
||||
(el) => isLineElement(el) && canBecomePolygon(el.points),
|
||||
);
|
||||
|
||||
if (shouldEnablePolygon) {
|
||||
const selectedElementsMap = arrayToMap(selectedElements);
|
||||
nextElements = elements.map((el) => {
|
||||
if (selectedElementsMap.has(el.id) && isLineElement(el)) {
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
normalizeLink,
|
||||
getLineHeight,
|
||||
} from "@excalidraw/common";
|
||||
import { getNonDeletedElements } from "@excalidraw/element";
|
||||
import { getNonDeletedElements, isValidPolygon } from "@excalidraw/element";
|
||||
import { normalizeFixedPoint } from "@excalidraw/element";
|
||||
import {
|
||||
updateElbowArrowPoints,
|
||||
@ -342,7 +342,11 @@ const restoreElement = (
|
||||
x,
|
||||
y,
|
||||
...(isLineElement(element)
|
||||
? { polygon: element.polygon ?? false }
|
||||
? {
|
||||
polygon: isValidPolygon(element.points)
|
||||
? element.polygon ?? false
|
||||
: false,
|
||||
}
|
||||
: {}),
|
||||
...getSizeFromPoints(points),
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user