Master merge

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Mark Tolmacs 2024-10-02 12:09:01 +02:00
parent b4d8b04d9e
commit 336fa9d002
No known key found for this signature in database
21 changed files with 189 additions and 157 deletions

View file

@ -38,7 +38,7 @@ import { DEFAULT_CANVAS_BACKGROUND_PICKS } from "../colors";
import type { ViewportBounds } from "../element/bounds";
import { setCursor } from "../cursor";
import { StoreAction } from "../store";
import { clamp, point, roundToStep } from "../../math";
import { clamp, pointFrom, roundToStep } from "../../math";
export const actionChangeViewBackgroundColor = register({
name: "changeViewBackgroundColor",
@ -324,7 +324,7 @@ export const zoomToFitBounds = ({
);
const centerScroll = centerScrollOn({
scenePoint: point(centerX, centerY),
scenePoint: pointFrom(centerX, centerY),
viewportDimensions: {
width: appState.width,
height: appState.height,

View file

@ -5,7 +5,7 @@ import type { AppState } from "./types";
import { getSvgPathFromStroke, sceneCoordsToViewportCoords } from "./utils";
import type App from "./components/App";
import { SVG_NS } from "./constants";
import { point } from "../math";
import { pointFrom } from "../math";
export interface Trail {
start(container: SVGSVGElement): void;
@ -136,7 +136,7 @@ export class AnimatedTrail implements Trail {
private drawTrail(trail: LaserPointer, state: AppState): string {
const stroke = trail
.getStrokeOutline(trail.options.size / state.zoom.value)
.map((p) => sceneCoordsToViewportCoords(point(p[0], p[1]), state));
.map((p) => sceneCoordsToViewportCoords(pointFrom(p[0], p[1]), state));
return getSvgPathFromStroke(stroke, true);
}

View file

@ -15,7 +15,7 @@ import type {
} from "../../element/types";
import { isRenderThrottlingEnabled } from "../../reactUtils";
import { renderInteractiveScene } from "../../renderer/interactiveScene";
import { point } from "../../../math";
import { pointFrom } from "../../../math";
type InteractiveCanvasProps = {
containerRef: React.RefObject<HTMLDivElement>;
@ -104,7 +104,7 @@ const InteractiveCanvas = (props: InteractiveCanvasProps) => {
remotePointerViewportCoords.set(
socketId,
sceneCoordsToViewportCoords(
point(user.pointer.x, user.pointer.y),
pointFrom(user.pointer.x, user.pointer.y),
props.appState,
),
);

View file

@ -81,7 +81,7 @@ export const isPointHittingLink = (
if (
!isMobile &&
appState.viewModeEnabled &&
hitElementBoundingBox(point(x, y), element, elementsMap)
hitElementBoundingBox(pointFrom(x, y), element, elementsMap)
) {
return true;
}

View file

@ -5,7 +5,7 @@ import { getElementAbsoluteCoords } from ".";
import { useExcalidrawAppState } from "../components/App";
import "./ElementCanvasButtons.scss";
import { point } from "../../math";
import { pointFrom } from "../../math";
const CONTAINER_PADDING = 5;
@ -16,7 +16,7 @@ const getContainerCoords = (
) => {
const [x1, y1] = getElementAbsoluteCoords(element, elementsMap);
const [viewportX, viewportY] = sceneCoordsToViewportCoords(
point(x1 + element.width, y1),
pointFrom(x1 + element.width, y1),
appState,
);
const x = viewportX - appState.offsetLeft + 10;

View file

@ -2,7 +2,7 @@ import type { Drawable } from "roughjs/bin/core";
import {
degrees,
degreesToRadians,
point,
pointFrom,
pointFromArray,
pointRotateRads,
radians,
@ -55,21 +55,21 @@ export const getArrowheadPoints = (
invariant(data.length === 6, "Op data length is not 6");
const p3 = point(data[4], data[5]);
const p2 = point(data[2], data[3]);
const p1 = point(data[0], data[1]);
const p3 = pointFrom(data[4], data[5]);
const p2 = pointFrom(data[2], data[3]);
const p1 = pointFrom(data[0], data[1]);
// We need to find p0 of the bezier curve.
// It is typically the last point of the previous
// curve; it can also be the position of moveTo operation.
const prevOp = ops[index - 1];
let p0 = point(0, 0);
let p0 = pointFrom(0, 0);
if (prevOp.op === "move") {
const p = pointFromArray(prevOp.data);
invariant(p != null, "Op data is not a point");
p0 = p;
} else if (prevOp.op === "bcurveTo") {
p0 = point(prevOp.data[4], prevOp.data[5]);
p0 = pointFrom(prevOp.data[4], prevOp.data[5]);
}
// B(t) = p0 * (1-t)^3 + 3p1 * t * (1-t)^2 + 3p2 * t^2 * (1-t) + p3 * t^3
@ -135,13 +135,13 @@ export const getArrowheadPoints = (
// Return points
const [x3, y3] = pointRotateRads(
point(xs, ys),
point(x2, y2),
pointFrom(xs, ys),
pointFrom(x2, y2),
radians((-angle * Math.PI) / 180),
);
const [x4, y4] = pointRotateRads(
point(xs, ys),
point(x2, y2),
pointFrom(xs, ys),
pointFrom(x2, y2),
degreesToRadians(angle),
);
@ -154,8 +154,8 @@ export const getArrowheadPoints = (
const [px, py] = element.points.length > 1 ? element.points[1] : [0, 0];
[ox, oy] = pointRotateRads(
point(x2 + minSize * 2, y2),
point(x2, y2),
pointFrom(x2 + minSize * 2, y2),
pointFrom(x2, y2),
radians(Math.atan2(py - y2, px - x2)),
);
} else {
@ -165,8 +165,8 @@ export const getArrowheadPoints = (
: [0, 0];
[ox, oy] = pointRotateRads(
point(x2 - minSize * 2, y2),
point(x2, y2),
pointFrom(x2 - minSize * 2, y2),
pointFrom(x2, y2),
radians(Math.atan2(y2 - py, x2 - px)),
);
}

View file

@ -227,7 +227,9 @@ export const intersectRectanguloidWithLine = (
lineSegmentIntersectionPoints(line<GlobalPoint>(rotatedA, rotatedB), s),
)
.filter((x) => x != null)
.map((j) => pointRotateRads<GlobalPoint>(j, center, element.angle));
.map((j: GlobalPoint) =>
pointRotateRads<GlobalPoint>(j, center, element.angle),
);
const cornerIntersections: GlobalPoint[] =
roundness > 0
? [
@ -335,7 +337,9 @@ export const intersectDiamondWithLine = (
)
.filter((x) => x != null)
// Rotate back intersection points
.map((p) => pointRotateRads<GlobalPoint>(p, center, element.angle));
.map((p: GlobalPoint) =>
pointRotateRads<GlobalPoint>(p, center, element.angle),
);
const corners = arcs
.flatMap((x) => arcLineInterceptPoints(x, line(rotatedA, rotatedB)))
.filter((x) => x != null)

View file

@ -4,7 +4,7 @@ import {
arcDistanceFromPoint,
ellipse,
ellipseDistanceFromPoint,
point,
pointFrom,
pointRotateRads,
radians,
rectangle,
@ -53,14 +53,14 @@ export const distanceToRectangleElement = (
p: GlobalPoint,
) => {
const r = rectangle(
point(element.x, element.y),
point(element.x + element.width, element.y + element.height),
pointFrom(element.x, element.y),
pointFrom(element.x + element.width, element.y + element.height),
);
// To emulate a rotated rectangle we rotate the point in the inverse angle
// instead. It's all the same distance-wise.
const rotatedPoint = pointRotateRads(
p,
point(element.x + element.width / 2, element.y + element.height / 2),
pointFrom(element.x + element.width / 2, element.y + element.height / 2),
radians(-element.angle),
);
const roundness = getCornerRadius(
@ -69,45 +69,45 @@ export const distanceToRectangleElement = (
);
const sideDistances = [
segment(
point(r[0][0] + roundness, r[0][1]),
point(r[1][0] - roundness, r[0][1]),
pointFrom(r[0][0] + roundness, r[0][1]),
pointFrom(r[1][0] - roundness, r[0][1]),
),
segment(
point(r[1][0], r[0][1] + roundness),
point(r[1][0], r[1][1] - roundness),
pointFrom(r[1][0], r[0][1] + roundness),
pointFrom(r[1][0], r[1][1] - roundness),
),
segment(
point(r[1][0] - roundness, r[1][1]),
point(r[0][0] + roundness, r[1][1]),
pointFrom(r[1][0] - roundness, r[1][1]),
pointFrom(r[0][0] + roundness, r[1][1]),
),
segment(
point(r[0][0], r[1][1] - roundness),
point(r[0][0], r[0][1] + roundness),
pointFrom(r[0][0], r[1][1] - roundness),
pointFrom(r[0][0], r[0][1] + roundness),
),
].map((s) => segmentDistanceToPoint(rotatedPoint, s));
const cornerDistances =
roundness > 0
? [
arc(
point(r[0][0] + roundness, r[0][1] + roundness),
pointFrom(r[0][0] + roundness, r[0][1] + roundness),
roundness,
radians(Math.PI),
radians((3 / 4) * Math.PI),
),
arc(
point(r[1][0] - roundness, r[0][1] + roundness),
pointFrom(r[1][0] - roundness, r[0][1] + roundness),
roundness,
radians((3 / 4) * Math.PI),
radians(0),
),
arc(
point(r[1][0] - roundness, r[1][1] - roundness),
pointFrom(r[1][0] - roundness, r[1][1] - roundness),
roundness,
radians(0),
radians((1 / 2) * Math.PI),
),
arc(
point(r[0][0] + roundness, r[1][1] - roundness),
pointFrom(r[0][0] + roundness, r[1][1] - roundness),
roundness,
radians((1 / 2) * Math.PI),
radians(Math.PI),
@ -132,7 +132,10 @@ export const distanceToDiamondElement = (
): number => {
const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] =
getDiamondPoints(element);
const center = point<GlobalPoint>((topX + bottomX) / 2, (topY + bottomY) / 2);
const center = pointFrom<GlobalPoint>(
(topX + bottomX) / 2,
(topY + bottomY) / 2,
);
const verticalRadius = getCornerRadius(Math.abs(topX - leftX), element);
const horizontalRadius = getCornerRadius(Math.abs(rightY - topY), element);
@ -140,10 +143,10 @@ export const distanceToDiamondElement = (
// points. It's all the same distance-wise.
const rotatedPoint = pointRotateRads(p, center, radians(-element.angle));
const [top, right, bottom, left]: GlobalPoint[] = [
point(element.x + topX, element.y + topY),
point(element.x + rightX, element.y + rightY),
point(element.x + bottomX, element.y + bottomY),
point(element.x + leftX, element.y + leftY),
pointFrom(element.x + topX, element.y + topY),
pointFrom(element.x + rightX, element.y + rightY),
pointFrom(element.x + bottomX, element.y + bottomY),
pointFrom(element.x + leftX, element.y + leftY),
];
const topRight = createDiamondSide(
@ -198,7 +201,7 @@ export const distanceToEllipseElement = (
element: ExcalidrawEllipseElement,
p: GlobalPoint,
): number => {
const center = point(
const center = pointFrom(
element.x + element.width / 2,
element.y + element.height / 2,
);

View file

@ -5,7 +5,7 @@ import { SHIFT_LOCKING_ANGLE } from "../constants";
import type { AppState, Offsets, Zoom } from "../types";
import { getCommonBounds, getElementBounds } from "./bounds";
import { viewportCoordsToSceneCoords } from "../utils";
import { point } from "../../math";
import { pointFrom } from "../../math";
// TODO: remove invisible elements consistently actions, so that invisible elements are not recorded by the store, exported, broadcasted or persisted
// - perhaps could be as part of a standalone 'cleanup' action, in addition to 'finalize'
@ -34,11 +34,11 @@ export const isElementInViewport = (
) => {
const [x1, y1, x2, y2] = getElementBounds(element, elementsMap); // scene coordinates
const topLeftSceneCoords = viewportCoordsToSceneCoords(
point(viewTransformations.offsetLeft, viewTransformations.offsetTop),
pointFrom(viewTransformations.offsetLeft, viewTransformations.offsetTop),
viewTransformations,
);
const bottomRightSceneCoords = viewportCoordsToSceneCoords(
point(
pointFrom(
viewTransformations.offsetLeft + width,
viewTransformations.offsetTop + height,
),
@ -69,14 +69,14 @@ export const isElementCompletelyInViewport = (
) => {
const [x1, y1, x2, y2] = getCommonBounds(elements, elementsMap); // scene coordinates
const topLeftSceneCoords = viewportCoordsToSceneCoords(
point(
pointFrom(
viewTransformations.offsetLeft + (padding?.left || 0),
viewTransformations.offsetTop + (padding?.top || 0),
),
viewTransformations,
);
const bottomRightSceneCoords = viewportCoordsToSceneCoords(
point(
pointFrom(
viewTransformations.offsetLeft + width - (padding?.right || 0),
viewTransformations.offsetTop + height - (padding?.bottom || 0),
),

View file

@ -30,7 +30,7 @@ import {
} from "./containerCache";
import type { ExtractSetType } from "../utility-types";
import type { GlobalPoint } from "../../math";
import { point } from "../../math";
import { pointFrom } from "../../math";
export const normalizeText = (text: string) => {
return (
@ -678,7 +678,7 @@ export const getContainerCenter = (
elementsMap: ElementsMap,
): GlobalPoint => {
if (!isArrowElement(container)) {
return point(
return pointFrom(
container.x + container.width / 2,
container.y + container.height / 2,
);
@ -694,7 +694,7 @@ export const getContainerCenter = (
container.points[index],
elementsMap,
);
return point(midPoint[0], midPoint[1]);
return pointFrom(midPoint[0], midPoint[1]);
}
const index = container.points.length / 2 - 1;
let midSegmentMidpoint = LinearElementEditor.getEditorMidPoints(
@ -711,7 +711,7 @@ export const getContainerCenter = (
elementsMap,
);
}
return point(midSegmentMidpoint[0], midSegmentMidpoint[1]);
return pointFrom(midSegmentMidpoint[0], midSegmentMidpoint[1]);
};
export const getContainerCoords = (container: NonDeletedExcalidrawElement) => {

View file

@ -11,16 +11,16 @@ import {
tupleToCoors,
viewportCoordsToSceneCoords,
} from "../utils";
import { point, type GlobalPoint } from "../../math";
import { pointFrom, type GlobalPoint } from "../../math";
const isOutsideViewPort = (appState: AppState, cords: Array<number>) => {
const [x1, y1, x2, y2] = cords;
const [viewportX1, viewportY1] = sceneCoordsToViewportCoords(
point(x1, y1),
pointFrom(x1, y1),
appState,
);
const [viewportX2, viewportY2] = sceneCoordsToViewportCoords(
point(x2, y2),
pointFrom(x2, y2),
appState,
);
return (
@ -77,7 +77,7 @@ export const calculateScrollCenter = (
elements,
tupleToCoors(
viewportCoordsToSceneCoords(
point(appState.scrollX, appState.scrollY),
pointFrom(appState.scrollX, appState.scrollY),
appState,
),
),
@ -88,7 +88,7 @@ export const calculateScrollCenter = (
const centerY = (y1 + y2) / 2;
return centerScrollOn({
scenePoint: point(centerX, centerY),
scenePoint: pointFrom(centerX, centerY),
viewportDimensions: { width: appState.width, height: appState.height },
zoom: appState.zoom,
});

View file

@ -1,5 +1,5 @@
import type { GlobalPoint, ViewportPoint } from "../math";
import { average, point } from "../math";
import { average, pointFrom } from "../math";
import { COLOR_PALETTE } from "./colors";
import type { EVENT } from "./constants";
import {
@ -436,7 +436,7 @@ export const viewportCoordsToSceneCoords = (
const x = (clientX - offsetLeft) / zoom.value - scrollX;
const y = (clientY - offsetTop) / zoom.value - scrollY;
return point<GlobalPoint>(x, y);
return pointFrom<GlobalPoint>(x, y);
};
export const sceneCoordsToViewportCoords = (
@ -457,7 +457,7 @@ export const sceneCoordsToViewportCoords = (
): ViewportPoint => {
const x = (sceneX + scrollX) * zoom.value + offsetLeft;
const y = (sceneY + scrollY) * zoom.value + offsetTop;
return point(x, y);
return pointFrom(x, y);
};
export const getGlobalCSSVariable = (name: string) =>