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 ===
|
app.state.editingLinearElement?.lastUncommittedPoint ===
|
||||||
element.points[element.points.length - 1];
|
element.points[element.points.length - 1];
|
||||||
|
|
||||||
|
const isPolygon = isLineElement(element) && element.polygon;
|
||||||
|
|
||||||
// break polygon if deleting start/end point
|
// break polygon if deleting start/end point
|
||||||
if (isLineElement(element) && element.polygon) {
|
if (
|
||||||
if (
|
isPolygon &&
|
||||||
pointIndices.includes(0) ||
|
// don't disable polygon if cleaning up uncommitted point
|
||||||
(pointIndices.includes(element.points.length - 1) &&
|
!isUncommittedPoint &&
|
||||||
// don't disable polygon if cleaning up uncommitted point
|
(pointIndices.includes(0) ||
|
||||||
!isUncommittedPoint)
|
pointIndices.includes(element.points.length - 1))
|
||||||
) {
|
) {
|
||||||
app.scene.mutateElement(element, { polygon: false });
|
app.scene.mutateElement(element, { polygon: false });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextPoints = element.points.filter((_, idx) => {
|
const nextPoints = element.points.filter((_, idx) => {
|
||||||
|
@ -36,6 +36,8 @@ import { ShapeCache } from "./ShapeCache";
|
|||||||
|
|
||||||
import { getElementAbsoluteCoords, type Bounds } from "./bounds";
|
import { getElementAbsoluteCoords, type Bounds } from "./bounds";
|
||||||
|
|
||||||
|
import { canBecomePolygon } from "./typeChecks";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ElementsMap,
|
ElementsMap,
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
@ -402,10 +404,17 @@ export const isPathALoop = (
|
|||||||
export const toggleLinePolygonState = (
|
export const toggleLinePolygonState = (
|
||||||
element: ExcalidrawLineElement,
|
element: ExcalidrawLineElement,
|
||||||
nextPolygonState: boolean,
|
nextPolygonState: boolean,
|
||||||
) => {
|
): {
|
||||||
|
polygon: ExcalidrawLineElement["polygon"];
|
||||||
|
points: ExcalidrawLineElement["points"];
|
||||||
|
} | null => {
|
||||||
const updatedPoints = [...element.points];
|
const updatedPoints = [...element.points];
|
||||||
|
|
||||||
if (nextPolygonState) {
|
if (nextPolygonState) {
|
||||||
|
if (!canBecomePolygon(element.points)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const firstPoint = updatedPoints[0];
|
const firstPoint = updatedPoints[0];
|
||||||
const lastPoint = updatedPoints[updatedPoints.length - 1];
|
const lastPoint = updatedPoints[updatedPoints.length - 1];
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { ROUNDNESS, assertNever } from "@excalidraw/common";
|
import { ROUNDNESS, assertNever } from "@excalidraw/common";
|
||||||
|
|
||||||
|
import { pointsEqual } from "@excalidraw/math";
|
||||||
|
|
||||||
import type { ElementOrToolType } from "@excalidraw/excalidraw/types";
|
import type { ElementOrToolType } from "@excalidraw/excalidraw/types";
|
||||||
|
|
||||||
import type { MarkNonNullable } from "@excalidraw/common/utility-types";
|
import type { MarkNonNullable } from "@excalidraw/common/utility-types";
|
||||||
@ -379,3 +381,26 @@ export const getLinearElementSubType = (
|
|||||||
}
|
}
|
||||||
return "line";
|
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,
|
bindOrUnbindLinearElement,
|
||||||
isBindingEnabled,
|
isBindingEnabled,
|
||||||
} from "@excalidraw/element/binding";
|
} from "@excalidraw/element/binding";
|
||||||
import { LinearElementEditor } from "@excalidraw/element/linearElementEditor";
|
import { isValidPolygon, LinearElementEditor } from "@excalidraw/element";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
isBindingElement,
|
isBindingElement,
|
||||||
@ -99,6 +99,12 @@ export const actionFinalize = register({
|
|||||||
scene,
|
scene,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (isLineElement(element) && !isValidPolygon(element.points)) {
|
||||||
|
scene.mutateElement(element, {
|
||||||
|
polygon: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
elements:
|
elements:
|
||||||
element.points.length < 2 || isInvisiblySmallElement(element)
|
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 (
|
if (
|
||||||
isBindingElement(element) &&
|
isBindingElement(element) &&
|
||||||
!isLoop &&
|
!isLoop &&
|
||||||
|
@ -24,7 +24,7 @@ import {
|
|||||||
reduceToCommonValue,
|
reduceToCommonValue,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
|
|
||||||
import { getNonDeletedElements } from "@excalidraw/element";
|
import { canBecomePolygon, getNonDeletedElements } from "@excalidraw/element";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
bindLinearElement,
|
bindLinearElement,
|
||||||
@ -364,18 +364,16 @@ export const actionChangeBackgroundColor = register({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedElements = app.scene.getSelectedElements(appState);
|
|
||||||
const shouldEnablePolygon = selectedElements.every((el) =>
|
|
||||||
isLineElement(el),
|
|
||||||
);
|
|
||||||
|
|
||||||
let nextElements;
|
let nextElements;
|
||||||
|
|
||||||
if (
|
const selectedElements = app.scene.getSelectedElements(appState);
|
||||||
shouldEnablePolygon &&
|
const shouldEnablePolygon =
|
||||||
value.currentItemBackgroundColor &&
|
!isTransparent(value.currentItemBackgroundColor) &&
|
||||||
!isTransparent(value.currentItemBackgroundColor)
|
selectedElements.every(
|
||||||
) {
|
(el) => isLineElement(el) && canBecomePolygon(el.points),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (shouldEnablePolygon) {
|
||||||
const selectedElementsMap = arrayToMap(selectedElements);
|
const selectedElementsMap = arrayToMap(selectedElements);
|
||||||
nextElements = elements.map((el) => {
|
nextElements = elements.map((el) => {
|
||||||
if (selectedElementsMap.has(el.id) && isLineElement(el)) {
|
if (selectedElementsMap.has(el.id) && isLineElement(el)) {
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
normalizeLink,
|
normalizeLink,
|
||||||
getLineHeight,
|
getLineHeight,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
import { getNonDeletedElements } from "@excalidraw/element";
|
import { getNonDeletedElements, isValidPolygon } from "@excalidraw/element";
|
||||||
import { normalizeFixedPoint } from "@excalidraw/element";
|
import { normalizeFixedPoint } from "@excalidraw/element";
|
||||||
import {
|
import {
|
||||||
updateElbowArrowPoints,
|
updateElbowArrowPoints,
|
||||||
@ -342,7 +342,11 @@ const restoreElement = (
|
|||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
...(isLineElement(element)
|
...(isLineElement(element)
|
||||||
? { polygon: element.polygon ?? false }
|
? {
|
||||||
|
polygon: isValidPolygon(element.points)
|
||||||
|
? element.polygon ?? false
|
||||||
|
: false,
|
||||||
|
}
|
||||||
: {}),
|
: {}),
|
||||||
...getSizeFromPoints(points),
|
...getSizeFromPoints(points),
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user