@weasel-js/labkit 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_dts/{DrawCommand-CitWPxMY.d.ts → DrawCommand-BkZztJsW.d.ts} +59 -1
- package/dist/_dts/{index-C6Yze7sQ.d.ts → index-CFlDPeZh.d.ts} +30 -1
- package/dist/_dts/{types-Si4Fw-1F.d.ts → types-x92Kfeme.d.ts} +14 -0
- package/dist/_dts/{useExperimentState-CJn2hHzd.d.ts → useExperimentState-D7EQnnwJ.d.ts} +47 -0
- package/dist/canvas/index.d.ts +13 -2
- package/dist/canvas/index.js +2 -2
- package/dist/{chunk-54IQ2DX7.js → chunk-574LJAV4.js} +3 -3
- package/dist/chunk-574LJAV4.js.map +1 -0
- package/dist/{chunk-VLAHRJOC.js → chunk-5R2ATYPJ.js} +2 -2
- package/dist/{chunk-VLAHRJOC.js.map → chunk-5R2ATYPJ.js.map} +1 -1
- package/dist/{chunk-R4TACNW7.js → chunk-BAPZPDDA.js} +631 -591
- package/dist/chunk-BAPZPDDA.js.map +1 -0
- package/dist/{chunk-PWC7AQZM.js → chunk-CPUJ3QXL.js} +2 -2
- package/dist/chunk-CPUJ3QXL.js.map +1 -0
- package/dist/{chunk-2ZRE7WGQ.js → chunk-DEWXYFEU.js} +6 -6
- package/dist/chunk-DEWXYFEU.js.map +1 -0
- package/dist/{chunk-3P56ZCCJ.js → chunk-DWV7SFKR.js} +601 -269
- package/dist/chunk-DWV7SFKR.js.map +1 -0
- package/dist/{chunk-53XSBIUK.js → chunk-KSTEW2AF.js} +18 -2
- package/dist/chunk-KSTEW2AF.js.map +1 -0
- package/dist/{chunk-HXZHVU4G.js → chunk-PMAU3SEE.js} +3 -3
- package/dist/chunk-PMAU3SEE.js.map +1 -0
- package/dist/{chunk-7BKDG73Z.js → chunk-RL2LOLNI.js} +2 -2
- package/dist/chunk-RL2LOLNI.js.map +1 -0
- package/dist/{chunk-2QNYYL3V.js → chunk-SFL7NFKN.js} +2 -2
- package/dist/chunk-SFL7NFKN.js.map +1 -0
- package/dist/controls/index.d.ts +4 -2
- package/dist/controls/index.js +1 -1
- package/dist/dragdrop/index.d.ts +2 -2
- package/dist/index.d.ts +180 -15
- package/dist/index.js +146 -37
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +6 -3
- package/dist/layers/index.js +1 -1
- package/dist/passthrough/weasel-canvas.d.ts +5 -1
- package/dist/passthrough/weasel-canvas.js +1 -1
- package/dist/passthrough/weasel-ui.d.ts +444 -7
- package/dist/passthrough/weasel-ui.js +2 -2
- package/dist/primitives/index.d.ts +13 -0
- package/dist/primitives/index.js +2 -2
- package/dist/state/index.d.ts +16 -3
- package/dist/state/index.js +2 -2
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +163 -6
- package/dist/ui/layers/index.d.ts +5 -0
- package/dist/ui/layers/index.js +3 -3
- package/dist/undo/index.d.ts +17 -2
- package/dist/undo/index.js +1 -1
- package/package.json +2 -1
- package/src/canvas/CanvasStack.tsx +4 -0
- package/src/canvas/CanvasStackContext.ts +3 -0
- package/src/canvas/canvasCoords.ts +2 -0
- package/src/canvas/useLayerScheduler.ts +2 -0
- package/src/controls/ControlPanel.tsx +2 -0
- package/src/controls/types.ts +14 -0
- package/src/instrument/capabilityDetector.ts +3 -0
- package/src/instrument/defineInstrument.ts +2 -0
- package/src/instrument/types.ts +29 -0
- package/src/instrument/validateConfigSchema.ts +5 -0
- package/src/lab/Lab.tsx +17 -2
- package/src/lab/LabContext.ts +6 -0
- package/src/lab/LabShell.tsx +4 -0
- package/src/lab/WorkspaceGrid.less +37 -5
- package/src/lab/WorkspaceGrid.stories.tsx +16 -0
- package/src/lab/WorkspaceGrid.test.tsx +84 -10
- package/src/lab/WorkspaceGrid.tsx +188 -12
- package/src/lab/index.ts +0 -2
- package/src/layers/LayerList.tsx +3 -0
- package/src/primitives/FpsMeter.tsx +1 -0
- package/src/primitives/ScaleIndicator.tsx +4 -0
- package/src/primitives/Sidebar.tsx +3 -0
- package/src/primitives/StatusBar.tsx +3 -0
- package/src/primitives/Toolbar.tsx +6 -0
- package/src/state/SingletonExperiment.tsx +1 -0
- package/src/state/adapters.ts +8 -0
- package/src/state/context.tsx +9 -0
- package/src/state/helpers.ts +13 -1
- package/src/state/store.test.ts +2 -1
- package/src/state/store.ts +25 -0
- package/src/state/types.ts +20 -0
- package/src/state/useExperimentState.ts +3 -0
- package/src/test-setup.ts +19 -0
- package/src/ui/layers/LayerStack.tsx +5 -0
- package/src/ui/properties/CurveField.tsx +4 -1
- package/src/ui/properties/EffectCard.tsx +12 -0
- package/src/ui/properties/PropertyGroup.tsx +1 -0
- package/src/ui/properties/PropertyPanel.tsx +28 -0
- package/src/undo/eventBus.ts +4 -0
- package/src/undo/undoStack.ts +11 -0
- package/src/workspace/DefaultSidebar.tsx +3 -0
- package/src/workspace/DefaultStatusBar.tsx +3 -0
- package/src/workspace/DefaultToolbar.tsx +3 -0
- package/src/workspace/Workspace.stories.tsx +1 -0
- package/src/workspace/Workspace.test.tsx +1 -0
- package/src/workspace/Workspace.tsx +3 -0
- package/src/workspace/WorkspaceChrome.tsx +4 -0
- package/src/workspace/index.ts +1 -0
- package/src/workspace/slotTypes.ts +9 -0
- package/src/workspace/workspaceOps.test.ts +34 -1
- package/src/workspace/workspaceOps.ts +24 -0
- package/dist/chunk-2QNYYL3V.js.map +0 -1
- package/dist/chunk-2ZRE7WGQ.js.map +0 -1
- package/dist/chunk-3P56ZCCJ.js.map +0 -1
- package/dist/chunk-53XSBIUK.js.map +0 -1
- package/dist/chunk-54IQ2DX7.js.map +0 -1
- package/dist/chunk-7BKDG73Z.js.map +0 -1
- package/dist/chunk-HXZHVU4G.js.map +0 -1
- package/dist/chunk-PWC7AQZM.js.map +0 -1
- package/dist/chunk-R4TACNW7.js.map +0 -1
- package/src/lab/gridDims.test.ts +0 -35
- package/src/lab/gridDims.ts +0 -11
|
@@ -3,7 +3,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
3
3
|
import earcut from 'earcut';
|
|
4
4
|
import polygonClipping from 'polygon-clipping';
|
|
5
5
|
|
|
6
|
-
// ../core/dist/chunk-
|
|
6
|
+
// ../core/dist/chunk-J3YC3GVF.js
|
|
7
7
|
|
|
8
8
|
// ../gestures/dist/index.js
|
|
9
9
|
var GESTURE_DESCRIPTORS = [
|
|
@@ -60,9 +60,8 @@ function formatRoute(r) {
|
|
|
60
60
|
const desc = getGestureDescriptor(r.gesture);
|
|
61
61
|
const phaseStr = `[${r.phases.map(formatPhaseAtom).join(",")}]`;
|
|
62
62
|
let out = `${phaseStr} ${r.gesture}`;
|
|
63
|
-
if (desc.arg) {
|
|
64
|
-
|
|
65
|
-
if (!isDefault) out += `(${r.arg})`;
|
|
63
|
+
if (desc.arg && r.arg !== void 0 && r.arg !== (desc.arg.default ?? "*")) {
|
|
64
|
+
out += `(${r.arg})`;
|
|
66
65
|
}
|
|
67
66
|
if (desc.hasTarget && r.target !== void 0 && r.target !== "*") {
|
|
68
67
|
out += ` => ${r.target}`;
|
|
@@ -288,7 +287,7 @@ function matchSpec(e, spec, isMac, phaseCtx) {
|
|
|
288
287
|
}
|
|
289
288
|
var EMPTY_ENGAGED = /* @__PURE__ */ new Set();
|
|
290
289
|
|
|
291
|
-
// ../core/dist/chunk-
|
|
290
|
+
// ../core/dist/chunk-J3YC3GVF.js
|
|
292
291
|
var DepRegistryContext = createContext(null);
|
|
293
292
|
function DepRegistryProvider({ children }) {
|
|
294
293
|
const sourcesRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -520,7 +519,8 @@ function ActionsProvider({ children }) {
|
|
|
520
519
|
const disp = dispatcherRef.current;
|
|
521
520
|
if (!disp) return null;
|
|
522
521
|
const r = wiredDepRegRef.current ?? depRegRef.current;
|
|
523
|
-
const
|
|
522
|
+
const a = actionsRef.current.get(id);
|
|
523
|
+
const deps = !r ? {} : a?.requires ? buildDepsFromRequires(a, r) : {
|
|
524
524
|
selection: r.get("selection"),
|
|
525
525
|
scene: r.get("scene"),
|
|
526
526
|
history: r.get("history"),
|
|
@@ -528,7 +528,7 @@ function ActionsProvider({ children }) {
|
|
|
528
528
|
pointer: r.get("pointer"),
|
|
529
529
|
activeTool: r.get("activeTool"),
|
|
530
530
|
booleansAdapter: r.get("booleansAdapter")
|
|
531
|
-
}
|
|
531
|
+
};
|
|
532
532
|
return disp.beginUiOngoing(id, deps, params);
|
|
533
533
|
}
|
|
534
534
|
};
|
|
@@ -699,7 +699,7 @@ function reportRouteConflicts(scopes, warn = (m) => console.warn(m)) {
|
|
|
699
699
|
return conflicts;
|
|
700
700
|
}
|
|
701
701
|
|
|
702
|
-
// ../geom/dist/chunk-
|
|
702
|
+
// ../geom/dist/chunk-KU7FXMOA.js
|
|
703
703
|
function cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t) {
|
|
704
704
|
const u = 1 - t;
|
|
705
705
|
const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
|
|
@@ -753,6 +753,12 @@ function cubicBounds(x0, y0, x1, y1, x2, y2, x3, y3) {
|
|
|
753
753
|
}
|
|
754
754
|
|
|
755
755
|
// ../geom/dist/index.js
|
|
756
|
+
function dot(ax, ay, bx, by) {
|
|
757
|
+
return ax * bx + ay * by;
|
|
758
|
+
}
|
|
759
|
+
function len2(x, y) {
|
|
760
|
+
return x * x + y * y;
|
|
761
|
+
}
|
|
756
762
|
function sign(n) {
|
|
757
763
|
return n > 0 ? 1 : n < 0 ? -1 : 0;
|
|
758
764
|
}
|
|
@@ -804,6 +810,15 @@ function segmentsCross(ax, ay, bx, by, cx, cy, dx, dy) {
|
|
|
804
810
|
const d4 = sign((bx - ax) * (dy - ay) - (by - ay) * (dx - ax));
|
|
805
811
|
return d1 !== d2 && d3 !== d4;
|
|
806
812
|
}
|
|
813
|
+
function pointSegmentDist2(px, py, ax, ay, bx, by) {
|
|
814
|
+
const vx = bx - ax, vy = by - ay;
|
|
815
|
+
const wx = px - ax, wy = py - ay;
|
|
816
|
+
const vv = len2(vx, vy);
|
|
817
|
+
let t = vv === 0 ? 0 : dot(wx, wy, vx, vy) / vv;
|
|
818
|
+
t = t < 0 ? 0 : t > 1 ? 1 : t;
|
|
819
|
+
const dx = px - (ax + t * vx), dy = py - (ay + t * vy);
|
|
820
|
+
return len2(dx, dy);
|
|
821
|
+
}
|
|
807
822
|
function transformCoords(coords, m) {
|
|
808
823
|
const out = new Float64Array(coords.length);
|
|
809
824
|
const a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5];
|
|
@@ -815,7 +830,7 @@ function transformCoords(coords, m) {
|
|
|
815
830
|
return out;
|
|
816
831
|
}
|
|
817
832
|
|
|
818
|
-
// ../core/dist/chunk-
|
|
833
|
+
// ../core/dist/chunk-4Z6J4IVH.js
|
|
819
834
|
function resolveUnit(v, unitSystem) {
|
|
820
835
|
if (typeof v === "number") return v;
|
|
821
836
|
if (!unitSystem) {
|
|
@@ -900,19 +915,36 @@ function boundsOfPath(path) {
|
|
|
900
915
|
return { kind: "rect", x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
901
916
|
}
|
|
902
917
|
var DEFAULT_FLATTEN_TOLERANCE = 0.5;
|
|
918
|
+
var MIN_FLATTEN_TOLERANCE = 1e-6;
|
|
919
|
+
function usableTolerance(tolerance) {
|
|
920
|
+
return tolerance > 0 ? tolerance : MIN_FLATTEN_TOLERANCE;
|
|
921
|
+
}
|
|
922
|
+
function finite6(a, b, c, d, e, f) {
|
|
923
|
+
return Number.isFinite(a) && Number.isFinite(b) && Number.isFinite(c) && Number.isFinite(d) && Number.isFinite(e) && Number.isFinite(f);
|
|
924
|
+
}
|
|
925
|
+
function finite8(a, b, c, d, e, f, g, h) {
|
|
926
|
+
return finite6(a, b, c, d, e, f) && Number.isFinite(g) && Number.isFinite(h);
|
|
927
|
+
}
|
|
903
928
|
function distPointToLine(px, py, ax, ay, bx, by) {
|
|
904
929
|
const dx = bx - ax;
|
|
905
930
|
const dy = by - ay;
|
|
906
|
-
const
|
|
907
|
-
if (
|
|
931
|
+
const len22 = dx * dx + dy * dy;
|
|
932
|
+
if (len22 === 0) {
|
|
908
933
|
const ex = px - ax;
|
|
909
934
|
const ey = py - ay;
|
|
910
935
|
return Math.sqrt(ex * ex + ey * ey);
|
|
911
936
|
}
|
|
912
937
|
const cross = (px - ax) * dy - (py - ay) * dx;
|
|
913
|
-
return Math.abs(cross) / Math.sqrt(
|
|
938
|
+
return Math.abs(cross) / Math.sqrt(len22);
|
|
914
939
|
}
|
|
915
940
|
function flattenCubic2(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
|
|
941
|
+
if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {
|
|
942
|
+
out.push(x3, y3);
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out);
|
|
946
|
+
}
|
|
947
|
+
function flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
|
|
916
948
|
const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);
|
|
917
949
|
const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);
|
|
918
950
|
if (Math.max(d1, d2) <= tolerance) {
|
|
@@ -925,10 +957,17 @@ function flattenCubic2(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
|
|
|
925
957
|
const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
|
|
926
958
|
const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;
|
|
927
959
|
const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;
|
|
928
|
-
|
|
929
|
-
|
|
960
|
+
flattenCubicRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out);
|
|
961
|
+
flattenCubicRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out);
|
|
930
962
|
}
|
|
931
963
|
function flattenQuadratic(x0, y0, x1, y1, x2, y2, tolerance, out) {
|
|
964
|
+
if (!finite6(x0, y0, x1, y1, x2, y2)) {
|
|
965
|
+
out.push(x2, y2);
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
flattenQuadraticRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out);
|
|
969
|
+
}
|
|
970
|
+
function flattenQuadraticRec(x0, y0, x1, y1, x2, y2, tolerance, out) {
|
|
932
971
|
const d = distPointToLine(x1, y1, x0, y0, x2, y2);
|
|
933
972
|
if (d <= tolerance) {
|
|
934
973
|
out.push(x2, y2);
|
|
@@ -937,11 +976,16 @@ function flattenQuadratic(x0, y0, x1, y1, x2, y2, tolerance, out) {
|
|
|
937
976
|
const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
|
|
938
977
|
const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
|
|
939
978
|
const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
|
|
940
|
-
|
|
941
|
-
|
|
979
|
+
flattenQuadraticRec(x0, y0, x01, y01, x012, y012, tolerance, out);
|
|
980
|
+
flattenQuadraticRec(x012, y012, x12, y12, x2, y2, tolerance, out);
|
|
942
981
|
}
|
|
943
982
|
function flattenCubicWithArcLen(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut) {
|
|
944
|
-
|
|
983
|
+
if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {
|
|
984
|
+
out.push(x3, y3);
|
|
985
|
+
arcOut.push(0);
|
|
986
|
+
return 0;
|
|
987
|
+
}
|
|
988
|
+
return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, arcOut, 0);
|
|
945
989
|
}
|
|
946
990
|
function flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut, accum) {
|
|
947
991
|
const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);
|
|
@@ -966,7 +1010,12 @@ function flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcO
|
|
|
966
1010
|
return accum;
|
|
967
1011
|
}
|
|
968
1012
|
function flattenQuadraticWithArcLen(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut) {
|
|
969
|
-
|
|
1013
|
+
if (!finite6(x0, y0, x1, y1, x2, y2)) {
|
|
1014
|
+
out.push(x2, y2);
|
|
1015
|
+
arcOut.push(0);
|
|
1016
|
+
return 0;
|
|
1017
|
+
}
|
|
1018
|
+
return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, arcOut, 0);
|
|
970
1019
|
}
|
|
971
1020
|
function flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut, accum) {
|
|
972
1021
|
const d = distPointToLine(x1, y1, x0, y0, x2, y2);
|
|
@@ -1159,22 +1208,6 @@ function polylineWithinThreshold(path, px, py, t2, tolerance) {
|
|
|
1159
1208
|
if (subOpen && checkSegments(false)) return true;
|
|
1160
1209
|
return false;
|
|
1161
1210
|
}
|
|
1162
|
-
function pointSegmentDist2(px, py, ax, ay, bx, by) {
|
|
1163
|
-
const dx = bx - ax;
|
|
1164
|
-
const dy = by - ay;
|
|
1165
|
-
const len2 = dx * dx + dy * dy;
|
|
1166
|
-
if (len2 === 0) {
|
|
1167
|
-
const ex2 = px - ax, ey2 = py - ay;
|
|
1168
|
-
return ex2 * ex2 + ey2 * ey2;
|
|
1169
|
-
}
|
|
1170
|
-
let t = ((px - ax) * dx + (py - ay) * dy) / len2;
|
|
1171
|
-
if (t < 0) t = 0;
|
|
1172
|
-
else if (t > 1) t = 1;
|
|
1173
|
-
const cx = ax + t * dx;
|
|
1174
|
-
const cy = ay + t * dy;
|
|
1175
|
-
const ex = px - cx, ey = py - cy;
|
|
1176
|
-
return ex * ex + ey * ey;
|
|
1177
|
-
}
|
|
1178
1211
|
var PathBuilder = class _PathBuilder {
|
|
1179
1212
|
cmds = [];
|
|
1180
1213
|
xs = [];
|
|
@@ -1563,7 +1596,7 @@ function createDeleteOp(args) {
|
|
|
1563
1596
|
}
|
|
1564
1597
|
registerOpFactory("delete", (args) => createDeleteOp(args));
|
|
1565
1598
|
|
|
1566
|
-
// ../core/dist/chunk-
|
|
1599
|
+
// ../core/dist/chunk-CSMF654J.js
|
|
1567
1600
|
function createTransformOp(args) {
|
|
1568
1601
|
const { id, from, to, label, coalesceKey = `transform:${id}` } = args;
|
|
1569
1602
|
return {
|
|
@@ -1644,7 +1677,7 @@ function snap(strategy, opts = {}) {
|
|
|
1644
1677
|
};
|
|
1645
1678
|
}
|
|
1646
1679
|
|
|
1647
|
-
// ../core/dist/chunk-
|
|
1680
|
+
// ../core/dist/chunk-J7LUY47N.js
|
|
1648
1681
|
function lockAspectWithModifier(opts = {}) {
|
|
1649
1682
|
const { key = "shift" } = opts;
|
|
1650
1683
|
return {
|
|
@@ -1840,7 +1873,7 @@ function materializePaste(adapter, snapshot, opts) {
|
|
|
1840
1873
|
return { ops, newIds, created };
|
|
1841
1874
|
}
|
|
1842
1875
|
|
|
1843
|
-
// ../core/dist/chunk-
|
|
1876
|
+
// ../core/dist/chunk-HGF5X6MZ.js
|
|
1844
1877
|
var counter = 0;
|
|
1845
1878
|
var registry = /* @__PURE__ */ new Map();
|
|
1846
1879
|
function getTexture(id) {
|
|
@@ -1998,7 +2031,7 @@ function chunks(params) {
|
|
|
1998
2031
|
return build({ tile: "chunks", ...params });
|
|
1999
2032
|
}
|
|
2000
2033
|
|
|
2001
|
-
// ../font/dist/
|
|
2034
|
+
// ../font/dist/chunk-3RSTZDXH.js
|
|
2002
2035
|
var subscribers = /* @__PURE__ */ new Set();
|
|
2003
2036
|
var generation = 0;
|
|
2004
2037
|
function glyphGeneration() {
|
|
@@ -2642,6 +2675,8 @@ function warnOnce(key, message) {
|
|
|
2642
2675
|
warned.add(key);
|
|
2643
2676
|
console.warn(message);
|
|
2644
2677
|
}
|
|
2678
|
+
|
|
2679
|
+
// ../font/dist/index.js
|
|
2645
2680
|
var TEXT_VERT_SRC = (
|
|
2646
2681
|
/* glsl */
|
|
2647
2682
|
`#version 300 es
|
|
@@ -2738,7 +2773,7 @@ var TEXT_SDF_UNIFORMS = [
|
|
|
2738
2773
|
];
|
|
2739
2774
|
var TEXT_SDF_ATTRIBUTES = ["a_position", "a_uv", "a_baselineY"];
|
|
2740
2775
|
|
|
2741
|
-
// ../modes/dist/chunk-
|
|
2776
|
+
// ../modes/dist/chunk-YAJYQMBG.js
|
|
2742
2777
|
var NORMAL = {
|
|
2743
2778
|
allows: [
|
|
2744
2779
|
"creates-selection",
|
|
@@ -2848,6 +2883,7 @@ function createHistory(adapter, options = {}) {
|
|
|
2848
2883
|
const logger = options.debug ?? SILENT;
|
|
2849
2884
|
let nextEntryId = 1;
|
|
2850
2885
|
let version = 0;
|
|
2886
|
+
let coalesceAnchorVersion = -1;
|
|
2851
2887
|
const listeners = /* @__PURE__ */ new Set();
|
|
2852
2888
|
function bump() {
|
|
2853
2889
|
version++;
|
|
@@ -2888,6 +2924,7 @@ function createHistory(adapter, options = {}) {
|
|
|
2888
2924
|
}
|
|
2889
2925
|
function canCoalesce(top, incoming) {
|
|
2890
2926
|
if (coalesceWindowMs <= 0) return false;
|
|
2927
|
+
if (version !== coalesceAnchorVersion) return false;
|
|
2891
2928
|
if (now() - top.timestamp > coalesceWindowMs) return false;
|
|
2892
2929
|
if (top.forwardOps.length === 0 || incoming.length === 0) return false;
|
|
2893
2930
|
if (top.forwardOps.length !== incoming.length) return false;
|
|
@@ -2925,9 +2962,9 @@ function createHistory(adapter, options = {}) {
|
|
|
2925
2962
|
for (const id of incoming) merged.add(id);
|
|
2926
2963
|
top.touchedIds = merged;
|
|
2927
2964
|
}
|
|
2928
|
-
dropRedo();
|
|
2929
2965
|
logger.log(`coalesce '${label}' into entry id=${top.id} (${ops.length} ops)`);
|
|
2930
2966
|
bump();
|
|
2967
|
+
coalesceAnchorVersion = version;
|
|
2931
2968
|
return;
|
|
2932
2969
|
}
|
|
2933
2970
|
logger.log(`push '${label}' (${ops.length} ops)`);
|
|
@@ -2935,6 +2972,7 @@ function createHistory(adapter, options = {}) {
|
|
|
2935
2972
|
dropRedo();
|
|
2936
2973
|
enforceLimit();
|
|
2937
2974
|
bump();
|
|
2975
|
+
coalesceAnchorVersion = version;
|
|
2938
2976
|
}
|
|
2939
2977
|
return {
|
|
2940
2978
|
apply(op, label) {
|
|
@@ -3040,7 +3078,11 @@ function createHistory(adapter, options = {}) {
|
|
|
3040
3078
|
return j;
|
|
3041
3079
|
},
|
|
3042
3080
|
resumeJournal(journal) {
|
|
3081
|
+
if (activeJournal !== null && activeJournal !== journal && activeJournal.isActive()) {
|
|
3082
|
+
throw new Error("A journal is already active \u2014 commit, cancel, or suspend it first");
|
|
3083
|
+
}
|
|
3043
3084
|
_resumeJournalInternal(journal);
|
|
3085
|
+
activeJournal = journal;
|
|
3044
3086
|
},
|
|
3045
3087
|
restore(snapshot) {
|
|
3046
3088
|
undoStack.length = 0;
|
|
@@ -3121,9 +3163,8 @@ function serialToEntry(se, custom, logger) {
|
|
|
3121
3163
|
label: se.label,
|
|
3122
3164
|
forwardOps,
|
|
3123
3165
|
baseOps,
|
|
3124
|
-
//
|
|
3125
|
-
//
|
|
3126
|
-
// freshly-typed one regardless of when it was originally pushed.
|
|
3166
|
+
// Coalescing is a within-session concept; a restored entry is never a
|
|
3167
|
+
// coalesce anchor, so its timestamp only has to be non-null.
|
|
3127
3168
|
timestamp: 0,
|
|
3128
3169
|
// Re-derive touchedIds from the rebuilt ops rather than trying to
|
|
3129
3170
|
// round-trip the Set through the serialized form (Sets aren't JSON-safe).
|
|
@@ -3131,7 +3172,7 @@ function serialToEntry(se, custom, logger) {
|
|
|
3131
3172
|
};
|
|
3132
3173
|
}
|
|
3133
3174
|
|
|
3134
|
-
// ../core/dist/chunk-
|
|
3175
|
+
// ../core/dist/chunk-AYGSXNY3.js
|
|
3135
3176
|
function worldToScreen(worldX, worldY, view) {
|
|
3136
3177
|
return [view.panX + worldX * view.zoom.x, view.panY + worldY * view.zoom.y];
|
|
3137
3178
|
}
|
|
@@ -3568,13 +3609,20 @@ var GLTextureCache = class {
|
|
|
3568
3609
|
}
|
|
3569
3610
|
gl;
|
|
3570
3611
|
map = /* @__PURE__ */ new Map();
|
|
3612
|
+
wraps = /* @__PURE__ */ new Map();
|
|
3571
3613
|
has(id) {
|
|
3572
3614
|
return this.map.has(id);
|
|
3573
3615
|
}
|
|
3574
|
-
/** Uploads once per id
|
|
3575
|
-
*
|
|
3616
|
+
/** Uploads the pixels once per id. `wrap` is re-applied whenever it differs
|
|
3617
|
+
* from what the id was last uploaded under: the same registered image can
|
|
3618
|
+
* be a clamped shader texture in one draw and a repeating pattern tile in
|
|
3619
|
+
* the next, and first-upload-wins gave the second one the first one's mode. */
|
|
3576
3620
|
upload(id, source, wrap = "clamp") {
|
|
3577
|
-
|
|
3621
|
+
const cached2 = this.map.get(id);
|
|
3622
|
+
if (cached2) {
|
|
3623
|
+
if (this.wraps.get(id) !== wrap) this.applyWrap(id, cached2, wrap);
|
|
3624
|
+
return id;
|
|
3625
|
+
}
|
|
3578
3626
|
const gl = this.gl;
|
|
3579
3627
|
const tex = gl.createTexture();
|
|
3580
3628
|
if (!tex) throw new Error(`GLTextureCache: createTexture failed for id="${id}"`);
|
|
@@ -3587,8 +3635,18 @@ var GLTextureCache = class {
|
|
|
3587
3635
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapMode);
|
|
3588
3636
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
3589
3637
|
this.map.set(id, tex);
|
|
3638
|
+
this.wraps.set(id, wrap);
|
|
3590
3639
|
return id;
|
|
3591
3640
|
}
|
|
3641
|
+
applyWrap(id, tex, wrap) {
|
|
3642
|
+
const gl = this.gl;
|
|
3643
|
+
const mode = wrap === "repeat" ? gl.REPEAT : gl.CLAMP_TO_EDGE;
|
|
3644
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
3645
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, mode);
|
|
3646
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, mode);
|
|
3647
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
3648
|
+
this.wraps.set(id, wrap);
|
|
3649
|
+
}
|
|
3592
3650
|
/** Create a single-channel R8 texture from raw bytes (full upload).
|
|
3593
3651
|
* No-op if `id` already exists. Same LINEAR/CLAMP params as `upload`;
|
|
3594
3652
|
* UNPACK_ALIGNMENT dropped to 1 for non-4-aligned row widths. */
|
|
@@ -3607,6 +3665,7 @@ var GLTextureCache = class {
|
|
|
3607
3665
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
3608
3666
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
3609
3667
|
this.map.set(id, tex);
|
|
3668
|
+
this.wraps.set(id, "clamp");
|
|
3610
3669
|
}
|
|
3611
3670
|
/** Patch a rect of an existing R8 texture with tightly-packed w×h bytes. */
|
|
3612
3671
|
subImageR8(id, x, y, w, h, data) {
|
|
@@ -3638,6 +3697,7 @@ var GLTextureCache = class {
|
|
|
3638
3697
|
gl.deleteTexture(tex);
|
|
3639
3698
|
}
|
|
3640
3699
|
this.map.clear();
|
|
3700
|
+
this.wraps.clear();
|
|
3641
3701
|
}
|
|
3642
3702
|
};
|
|
3643
3703
|
var GLImageCache = class {
|
|
@@ -4287,6 +4347,13 @@ var GroupState = class {
|
|
|
4287
4347
|
this.alphaStack.push(nextAlpha);
|
|
4288
4348
|
this.colorMatrixStack.push(nextCM);
|
|
4289
4349
|
}
|
|
4350
|
+
/** Drop every pushed frame, leaving the root. A frame that throws part-way
|
|
4351
|
+
* down the tree never pops, and the next frame would draw under leftovers. */
|
|
4352
|
+
reset() {
|
|
4353
|
+
this.transformStack.length = 1;
|
|
4354
|
+
this.alphaStack.length = 1;
|
|
4355
|
+
this.colorMatrixStack.length = 1;
|
|
4356
|
+
}
|
|
4290
4357
|
pop() {
|
|
4291
4358
|
if (this.transformStack.length <= 1) {
|
|
4292
4359
|
throw new Error("GroupState.pop: cannot pop root frame");
|
|
@@ -4934,16 +5001,28 @@ function verticalAlignOffset(align, boxHeight, textHeight) {
|
|
|
4934
5001
|
return align === "center" ? slack / 2 : slack;
|
|
4935
5002
|
}
|
|
4936
5003
|
var NUM_RE = /[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g;
|
|
5004
|
+
var NUM_RE_AT = /[+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/y;
|
|
5005
|
+
function isCommandLetter(d, j) {
|
|
5006
|
+
const c = d[j];
|
|
5007
|
+
if (!/[A-Za-z]/.test(c)) return false;
|
|
5008
|
+
if (c !== "e" && c !== "E") return true;
|
|
5009
|
+
if (!/[\d.]/.test(d[j - 1] ?? "")) return true;
|
|
5010
|
+
const k = d[j + 1] === "+" || d[j + 1] === "-" ? j + 2 : j + 1;
|
|
5011
|
+
return !/\d/.test(d[k] ?? "");
|
|
5012
|
+
}
|
|
4937
5013
|
function tokenize(d) {
|
|
4938
5014
|
const out = [];
|
|
4939
5015
|
let i = 0;
|
|
4940
5016
|
while (i < d.length) {
|
|
4941
|
-
|
|
4942
|
-
if (/[A-Za-z]/.test(ch)) {
|
|
5017
|
+
if (isCommandLetter(d, i)) {
|
|
4943
5018
|
let j = i + 1;
|
|
4944
|
-
while (j < d.length &&
|
|
5019
|
+
while (j < d.length && !isCommandLetter(d, j)) j++;
|
|
4945
5020
|
const argSlice = d.slice(i + 1, j);
|
|
4946
|
-
|
|
5021
|
+
const cmd = d[i];
|
|
5022
|
+
out.push({
|
|
5023
|
+
cmd,
|
|
5024
|
+
args: cmd === "A" || cmd === "a" ? readArcArgs(argSlice) : readNumbers(argSlice)
|
|
5025
|
+
});
|
|
4947
5026
|
i = j;
|
|
4948
5027
|
} else {
|
|
4949
5028
|
i++;
|
|
@@ -4961,6 +5040,30 @@ function readNumbers(s) {
|
|
|
4961
5040
|
}
|
|
4962
5041
|
return out;
|
|
4963
5042
|
}
|
|
5043
|
+
function readArcArgs(s) {
|
|
5044
|
+
const out = [];
|
|
5045
|
+
let i = 0;
|
|
5046
|
+
while (i < s.length) {
|
|
5047
|
+
const c = s[i];
|
|
5048
|
+
if (c === "," || c === " " || c === " " || c === "\n" || c === "\r") {
|
|
5049
|
+
i++;
|
|
5050
|
+
continue;
|
|
5051
|
+
}
|
|
5052
|
+
const slot = out.length % 7;
|
|
5053
|
+
if (slot === 3 || slot === 4) {
|
|
5054
|
+
if (c !== "0" && c !== "1") return out;
|
|
5055
|
+
out.push(c === "1" ? 1 : 0);
|
|
5056
|
+
i++;
|
|
5057
|
+
continue;
|
|
5058
|
+
}
|
|
5059
|
+
NUM_RE_AT.lastIndex = i;
|
|
5060
|
+
const m = NUM_RE_AT.exec(s);
|
|
5061
|
+
if (!m) return out;
|
|
5062
|
+
out.push(Number(m[0]));
|
|
5063
|
+
i = NUM_RE_AT.lastIndex;
|
|
5064
|
+
}
|
|
5065
|
+
return out;
|
|
5066
|
+
}
|
|
4964
5067
|
var ARG_COUNTS = {
|
|
4965
5068
|
M: 2,
|
|
4966
5069
|
L: 2,
|
|
@@ -5151,9 +5254,9 @@ function arcToCubics(x1, y1, x2, y2, rx, ry, xAxisRotationDeg, largeArc, sweep,
|
|
|
5151
5254
|
const cx = cosPhi * cxp - sinPhi * cyp + (x1 + x2) / 2;
|
|
5152
5255
|
const cy = sinPhi * cxp + cosPhi * cyp + (y1 + y2) / 2;
|
|
5153
5256
|
const angle = (ux, uy, vx, vy) => {
|
|
5154
|
-
const
|
|
5257
|
+
const dot2 = ux * vx + uy * vy;
|
|
5155
5258
|
const len = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
|
|
5156
|
-
let a = Math.acos(Math.max(-1, Math.min(1,
|
|
5259
|
+
let a = Math.acos(Math.max(-1, Math.min(1, dot2 / len)));
|
|
5157
5260
|
if (ux * vy - uy * vx < 0) a = -a;
|
|
5158
5261
|
return a;
|
|
5159
5262
|
};
|
|
@@ -5865,42 +5968,42 @@ var MAX_VERTICES_PER_BATCH = 32768;
|
|
|
5865
5968
|
var FLOATS_PER_VERTEX = 6;
|
|
5866
5969
|
var INITIAL_VERTICES = 256;
|
|
5867
5970
|
var INITIAL_INDICES = 384;
|
|
5971
|
+
var SOLID_RING_SIZE = 64;
|
|
5972
|
+
var SOLID_RING_SLOT_VERTICES = 1024;
|
|
5973
|
+
var SOLID_RING_SLOT_INDICES = 3072;
|
|
5974
|
+
var SOLID_LARGE_RING_SIZE = 4;
|
|
5975
|
+
function doubledTo(from, need) {
|
|
5976
|
+
let capacity = from;
|
|
5977
|
+
while (capacity < need) capacity *= 2;
|
|
5978
|
+
return capacity;
|
|
5979
|
+
}
|
|
5868
5980
|
var SolidBatch = class {
|
|
5869
5981
|
gl;
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5982
|
+
aPos;
|
|
5983
|
+
aColor;
|
|
5984
|
+
/** Cycled per flush, and created on first use so a renderer that flushes
|
|
5985
|
+
* rarely allocates as few slots as it flushes. */
|
|
5986
|
+
ring = new Array(SOLID_RING_SIZE).fill(void 0);
|
|
5987
|
+
next = 0;
|
|
5988
|
+
/** The same, for flushes past a slot's capacity; these sets grow to fit. */
|
|
5989
|
+
largeRing = new Array(SOLID_LARGE_RING_SIZE).fill(void 0);
|
|
5990
|
+
nextLarge = 0;
|
|
5873
5991
|
verts = new Float32Array(INITIAL_VERTICES * FLOATS_PER_VERTEX);
|
|
5874
5992
|
idx = new Uint32Array(INITIAL_INDICES);
|
|
5875
5993
|
nVerts = 0;
|
|
5876
5994
|
nIdx = 0;
|
|
5877
|
-
/**
|
|
5878
|
-
|
|
5879
|
-
|
|
5995
|
+
/** Whether the staged run is rects alone, so its indices are the canonical
|
|
5996
|
+
* quad pattern and a slot already holding that pattern needs no upload. */
|
|
5997
|
+
pureRects = true;
|
|
5880
5998
|
constructor(gl, prog) {
|
|
5881
5999
|
const aPos = prog.attribute("a_position");
|
|
5882
6000
|
const aColor = prog.attribute("a_vertexColor");
|
|
5883
6001
|
if (aPos === void 0 || aColor === void 0) {
|
|
5884
6002
|
throw new Error("SolidBatch: vertex-color program is missing a_position / a_vertexColor");
|
|
5885
6003
|
}
|
|
5886
|
-
const vao = gl.createVertexArray();
|
|
5887
|
-
const vbo = gl.createBuffer();
|
|
5888
|
-
const ibo = gl.createBuffer();
|
|
5889
|
-
if (!vao || !vbo || !ibo) throw new Error("SolidBatch: failed to create GL objects");
|
|
5890
6004
|
this.gl = gl;
|
|
5891
|
-
this.
|
|
5892
|
-
this.
|
|
5893
|
-
this.ibo = ibo;
|
|
5894
|
-
const stride = FLOATS_PER_VERTEX * 4;
|
|
5895
|
-
gl.bindVertexArray(vao);
|
|
5896
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
5897
|
-
gl.enableVertexAttribArray(aPos);
|
|
5898
|
-
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, stride, 0);
|
|
5899
|
-
gl.enableVertexAttribArray(aColor);
|
|
5900
|
-
gl.vertexAttribPointer(aColor, 4, gl.FLOAT, false, stride, 8);
|
|
5901
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
|
|
5902
|
-
gl.bindVertexArray(null);
|
|
5903
|
-
this.growGpu(INITIAL_VERTICES, INITIAL_INDICES);
|
|
6005
|
+
this.aPos = aPos;
|
|
6006
|
+
this.aColor = aColor;
|
|
5904
6007
|
}
|
|
5905
6008
|
get length() {
|
|
5906
6009
|
return this.nIdx;
|
|
@@ -5970,6 +6073,7 @@ var SolidBatch = class {
|
|
|
5970
6073
|
const srcIdx = mesh.indices;
|
|
5971
6074
|
const n = src.length >> 1;
|
|
5972
6075
|
this.reserve(n, srcIdx.length);
|
|
6076
|
+
this.pureRects = false;
|
|
5973
6077
|
const v = this.verts;
|
|
5974
6078
|
let i = this.nVerts * FLOATS_PER_VERTEX;
|
|
5975
6079
|
const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];
|
|
@@ -5990,67 +6094,109 @@ var SolidBatch = class {
|
|
|
5990
6094
|
this.nVerts += n;
|
|
5991
6095
|
this.nIdx += srcIdx.length;
|
|
5992
6096
|
}
|
|
5993
|
-
/** Upload the staged geometry and bind
|
|
5994
|
-
* count for the caller's `drawElements`. */
|
|
6097
|
+
/** Upload the staged geometry into the next set of buffers and bind its VAO.
|
|
6098
|
+
* Returns the index count for the caller's `drawElements`. */
|
|
5995
6099
|
uploadAndBind() {
|
|
5996
6100
|
const gl = this.gl;
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
gl.bindVertexArray(this.vao);
|
|
6001
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
|
|
6101
|
+
const set = this.nVerts <= SOLID_RING_SLOT_VERTICES && this.nIdx <= SOLID_RING_SLOT_INDICES ? this.nextRingSlot() : this.nextLargeSlot();
|
|
6102
|
+
gl.bindVertexArray(set.vao);
|
|
6103
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, set.vbo);
|
|
6002
6104
|
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verts, 0, this.nVerts * FLOATS_PER_VERTEX);
|
|
6003
|
-
|
|
6105
|
+
const rects = this.pureRects ? this.nVerts >> 2 : -1;
|
|
6106
|
+
if (rects < 0 || rects !== set.indexRects) {
|
|
6107
|
+
gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, this.idx, 0, this.nIdx);
|
|
6108
|
+
set.indexRects = rects;
|
|
6109
|
+
}
|
|
6004
6110
|
return this.nIdx;
|
|
6005
6111
|
}
|
|
6006
6112
|
reset() {
|
|
6007
6113
|
this.nVerts = 0;
|
|
6008
6114
|
this.nIdx = 0;
|
|
6115
|
+
this.pureRects = true;
|
|
6009
6116
|
}
|
|
6010
6117
|
dispose() {
|
|
6011
|
-
const
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6118
|
+
for (const set of [...this.ring, ...this.largeRing]) {
|
|
6119
|
+
if (set) this.deleteSet(set);
|
|
6120
|
+
}
|
|
6121
|
+
this.ring.fill(void 0);
|
|
6122
|
+
this.largeRing.fill(void 0);
|
|
6015
6123
|
}
|
|
6016
6124
|
/** Grow the CPU arrays so `vertices` / `indices` more fit. */
|
|
6017
6125
|
reserve(vertices, indices) {
|
|
6018
6126
|
const needVerts = (this.nVerts + vertices) * FLOATS_PER_VERTEX;
|
|
6019
6127
|
if (needVerts > this.verts.length) {
|
|
6020
|
-
|
|
6021
|
-
while (len < needVerts) len *= 2;
|
|
6022
|
-
const grown = new Float32Array(len);
|
|
6128
|
+
const grown = new Float32Array(doubledTo(this.verts.length, needVerts));
|
|
6023
6129
|
grown.set(this.verts);
|
|
6024
6130
|
this.verts = grown;
|
|
6025
6131
|
}
|
|
6026
6132
|
const needIdx = this.nIdx + indices;
|
|
6027
6133
|
if (needIdx > this.idx.length) {
|
|
6028
|
-
|
|
6029
|
-
while (len < needIdx) len *= 2;
|
|
6030
|
-
const grown = new Uint32Array(len);
|
|
6134
|
+
const grown = new Uint32Array(doubledTo(this.idx.length, needIdx));
|
|
6031
6135
|
grown.set(this.idx);
|
|
6032
6136
|
this.idx = grown;
|
|
6033
6137
|
}
|
|
6034
6138
|
}
|
|
6035
|
-
|
|
6036
|
-
|
|
6139
|
+
nextRingSlot() {
|
|
6140
|
+
const slot = this.next;
|
|
6141
|
+
this.next = (slot + 1) % SOLID_RING_SIZE;
|
|
6142
|
+
const existing = this.ring[slot];
|
|
6143
|
+
if (existing) return existing;
|
|
6144
|
+
const set = this.createSet(SOLID_RING_SLOT_VERTICES, SOLID_RING_SLOT_INDICES);
|
|
6145
|
+
this.ring[slot] = set;
|
|
6146
|
+
return set;
|
|
6147
|
+
}
|
|
6148
|
+
nextLargeSlot() {
|
|
6037
6149
|
const gl = this.gl;
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6150
|
+
const slot = this.nextLarge;
|
|
6151
|
+
this.nextLarge = (slot + 1) % SOLID_LARGE_RING_SIZE;
|
|
6152
|
+
let set = this.largeRing[slot];
|
|
6153
|
+
if (!set) {
|
|
6154
|
+
set = this.createSet(
|
|
6155
|
+
doubledTo(SOLID_RING_SLOT_VERTICES, this.nVerts),
|
|
6156
|
+
doubledTo(SOLID_RING_SLOT_INDICES, this.nIdx)
|
|
6157
|
+
);
|
|
6158
|
+
this.largeRing[slot] = set;
|
|
6159
|
+
return set;
|
|
6160
|
+
}
|
|
6161
|
+
if (this.nVerts > set.vertexCapacity) {
|
|
6162
|
+
set.vertexCapacity = doubledTo(set.vertexCapacity, this.nVerts);
|
|
6163
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, set.vbo);
|
|
6164
|
+
gl.bufferData(gl.ARRAY_BUFFER, set.vertexCapacity * FLOATS_PER_VERTEX * 4, gl.DYNAMIC_DRAW);
|
|
6165
|
+
}
|
|
6166
|
+
if (this.nIdx > set.indexCapacity) {
|
|
6167
|
+
set.indexCapacity = doubledTo(set.indexCapacity, this.nIdx);
|
|
6168
|
+
gl.bindVertexArray(set.vao);
|
|
6169
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, set.ibo);
|
|
6170
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, set.indexCapacity * 4, gl.DYNAMIC_DRAW);
|
|
6051
6171
|
gl.bindVertexArray(null);
|
|
6052
|
-
|
|
6172
|
+
set.indexRects = -1;
|
|
6053
6173
|
}
|
|
6174
|
+
return set;
|
|
6175
|
+
}
|
|
6176
|
+
createSet(vertices, indices) {
|
|
6177
|
+
const gl = this.gl;
|
|
6178
|
+
const vao = gl.createVertexArray();
|
|
6179
|
+
const vbo = gl.createBuffer();
|
|
6180
|
+
const ibo = gl.createBuffer();
|
|
6181
|
+
if (!vao || !vbo || !ibo) throw new Error("SolidBatch: failed to create GL objects");
|
|
6182
|
+
const stride = FLOATS_PER_VERTEX * 4;
|
|
6183
|
+
gl.bindVertexArray(vao);
|
|
6184
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
6185
|
+
gl.bufferData(gl.ARRAY_BUFFER, vertices * stride, gl.DYNAMIC_DRAW);
|
|
6186
|
+
gl.enableVertexAttribArray(this.aPos);
|
|
6187
|
+
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, stride, 0);
|
|
6188
|
+
gl.enableVertexAttribArray(this.aColor);
|
|
6189
|
+
gl.vertexAttribPointer(this.aColor, 4, gl.FLOAT, false, stride, 8);
|
|
6190
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
|
|
6191
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices * 4, gl.DYNAMIC_DRAW);
|
|
6192
|
+
gl.bindVertexArray(null);
|
|
6193
|
+
return { vao, vbo, ibo, vertexCapacity: vertices, indexCapacity: indices, indexRects: -1 };
|
|
6194
|
+
}
|
|
6195
|
+
deleteSet(set) {
|
|
6196
|
+
const gl = this.gl;
|
|
6197
|
+
gl.deleteBuffer(set.vbo);
|
|
6198
|
+
gl.deleteBuffer(set.ibo);
|
|
6199
|
+
gl.deleteVertexArray(set.vao);
|
|
6054
6200
|
}
|
|
6055
6201
|
};
|
|
6056
6202
|
var FRAME_UPLOADS = /* @__PURE__ */ new WeakMap();
|
|
@@ -6073,6 +6219,25 @@ function sameValues(prev, next) {
|
|
|
6073
6219
|
for (let i = 0; i < prev.length; i++) if (prev[i] !== next[i]) return false;
|
|
6074
6220
|
return true;
|
|
6075
6221
|
}
|
|
6222
|
+
function setColorUniform(ctx, prog, r, g, b, a) {
|
|
6223
|
+
const loc = prog.uniform("u_color");
|
|
6224
|
+
if (loc === void 0) return;
|
|
6225
|
+
const uploaded = uploadedFor(ctx, prog);
|
|
6226
|
+
const prev = uploaded.color;
|
|
6227
|
+
if (prev !== void 0 && prev[0] === r && prev[1] === g && prev[2] === b && prev[3] === a) {
|
|
6228
|
+
return;
|
|
6229
|
+
}
|
|
6230
|
+
ctx.gl.uniform4f(loc, r, g, b, a);
|
|
6231
|
+
uploaded.color = [r, g, b, a];
|
|
6232
|
+
}
|
|
6233
|
+
function setAlphaUniform(ctx, prog, alpha) {
|
|
6234
|
+
const loc = prog.uniform("u_alpha");
|
|
6235
|
+
if (loc === void 0) return;
|
|
6236
|
+
const uploaded = uploadedFor(ctx, prog);
|
|
6237
|
+
if (uploaded.alpha === alpha) return;
|
|
6238
|
+
ctx.gl.uniform1f(loc, alpha);
|
|
6239
|
+
uploaded.alpha = alpha;
|
|
6240
|
+
}
|
|
6076
6241
|
var BATCH_MODEL = mat3.identity();
|
|
6077
6242
|
function projFor(ctx) {
|
|
6078
6243
|
let proj = FRAME_PROJ.get(ctx);
|
|
@@ -6365,8 +6530,8 @@ function flushSolids(ctx) {
|
|
|
6365
6530
|
gl.useProgram(prog.handle);
|
|
6366
6531
|
const indexCount = batch.uploadAndBind();
|
|
6367
6532
|
setProjAndModel(ctx, prog, BATCH_MODEL);
|
|
6368
|
-
|
|
6369
|
-
|
|
6533
|
+
setColorUniform(ctx, prog, 1, 1, 1, 1);
|
|
6534
|
+
setAlphaUniform(ctx, prog, staged.alpha);
|
|
6370
6535
|
setColorMatrixUniforms(ctx, prog, staged.colorMatrix);
|
|
6371
6536
|
applyClipTest(ctx, staged.clipDepth);
|
|
6372
6537
|
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_INT, 0);
|
|
@@ -6431,10 +6596,9 @@ function setProjAndModel(ctx, prog, model = ctx.state.transform) {
|
|
|
6431
6596
|
}
|
|
6432
6597
|
}
|
|
6433
6598
|
function setSolidPaintUniforms(ctx, prog, color, opacity) {
|
|
6434
|
-
const gl = ctx.gl;
|
|
6435
6599
|
const [r, g, b, a] = resolveColor(color);
|
|
6436
|
-
|
|
6437
|
-
|
|
6600
|
+
setColorUniform(ctx, prog, r, g, b, a * (opacity ?? 1));
|
|
6601
|
+
setAlphaUniform(ctx, prog, ctx.state.alpha);
|
|
6438
6602
|
}
|
|
6439
6603
|
function drawPathFillByKind(ctx, fill, handle) {
|
|
6440
6604
|
const kind = fill.fill ?? "solid";
|
|
@@ -6480,7 +6644,7 @@ function drawPathFillPattern(ctx, fill, handle) {
|
|
|
6480
6644
|
ctx.textureCache.bind(tex.id, 0);
|
|
6481
6645
|
gl.uniform1i(ctx.patternFill.uniform("u_sampler"), 0);
|
|
6482
6646
|
gl.uniform1f(ctx.patternFill.uniform("u_opacity"), fill.opacity ?? 1);
|
|
6483
|
-
|
|
6647
|
+
setAlphaUniform(ctx, ctx.patternFill, ctx.state.alpha);
|
|
6484
6648
|
applyClipTest(ctx);
|
|
6485
6649
|
gl.drawElements(gl.TRIANGLES, handle.indexCount, gl.UNSIGNED_INT, 0);
|
|
6486
6650
|
gl.bindVertexArray(null);
|
|
@@ -6504,7 +6668,7 @@ function drawPathFillGradient(ctx, fill, handle) {
|
|
|
6504
6668
|
gl.uniformMatrix3fv(ctx.gradFill.uniform("u_worldInv"), false, gradientSpaceInverse(ctx, fill.units));
|
|
6505
6669
|
ctx.gradRampCache.bind(key, 0);
|
|
6506
6670
|
gl.uniform1i(ctx.gradFill.uniform("u_ramp"), 0);
|
|
6507
|
-
|
|
6671
|
+
setAlphaUniform(ctx, ctx.gradFill, ctx.state.alpha);
|
|
6508
6672
|
gl.uniform1f(ctx.gradFill.uniform("u_opacity"), fill.opacity ?? 1);
|
|
6509
6673
|
if (fill.fill === "linear-gradient") {
|
|
6510
6674
|
gl.uniform1i(ctx.gradFill.uniform("u_gradKind"), 0);
|
|
@@ -6654,6 +6818,7 @@ function drawPathStrokeUnclipped(ctx, cmd) {
|
|
|
6654
6818
|
gl.enableVertexAttribArray(aVColorLoc);
|
|
6655
6819
|
gl.vertexAttribPointer(aVColorLoc, 4, gl.FLOAT, false, 0, 0);
|
|
6656
6820
|
}
|
|
6821
|
+
applyClipTest(ctx);
|
|
6657
6822
|
gl.drawElements(gl.TRIANGLES, handle.indexCount, gl.UNSIGNED_INT, 0);
|
|
6658
6823
|
gl.bindVertexArray(null);
|
|
6659
6824
|
gl.deleteBuffer(colorVbo);
|
|
@@ -6769,7 +6934,7 @@ function drawText(ctx, cmd) {
|
|
|
6769
6934
|
preparedPrograms.add(prog);
|
|
6770
6935
|
setProjAndModel(ctx, prog);
|
|
6771
6936
|
setColorMatrixUniforms(ctx, prog);
|
|
6772
|
-
|
|
6937
|
+
setAlphaUniform(ctx, prog, ctx.state.alpha);
|
|
6773
6938
|
}
|
|
6774
6939
|
drawTextGroup(ctx, group, prog, dx, dy);
|
|
6775
6940
|
}
|
|
@@ -6887,8 +7052,8 @@ function drawTextDecorations(ctx, decorations, dx, dy) {
|
|
|
6887
7052
|
if (!ibo) throw new Error("drawTextDecorations: createBuffer (IBO) returned null");
|
|
6888
7053
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
|
|
6889
7054
|
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.DYNAMIC_DRAW);
|
|
6890
|
-
|
|
6891
|
-
|
|
7055
|
+
setColorUniform(ctx, prog, rgba[0], rgba[1], rgba[2], rgba[3]);
|
|
7056
|
+
setAlphaUniform(ctx, prog, ctx.state.alpha);
|
|
6892
7057
|
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_INT, 0);
|
|
6893
7058
|
gl.bindVertexArray(null);
|
|
6894
7059
|
gl.deleteVertexArray(vao);
|
|
@@ -6972,7 +7137,7 @@ function drawTextGroup(ctx, group, prog, dx, dy) {
|
|
|
6972
7137
|
if ("color" in group.fill) {
|
|
6973
7138
|
[r, g, b, a] = resolveColor(group.fill.color);
|
|
6974
7139
|
}
|
|
6975
|
-
|
|
7140
|
+
setColorUniform(ctx, prog, r, g, b, a);
|
|
6976
7141
|
const synthBoldAmount = group.synthetic.bold ? 0.08 : 0;
|
|
6977
7142
|
const uSynthBold = prog.uniform("u_synthBold");
|
|
6978
7143
|
if (uSynthBold !== void 0) gl.uniform1f(uSynthBold, synthBoldAmount);
|
|
@@ -6988,70 +7153,98 @@ function drawTextGroup(ctx, group, prog, dx, dy) {
|
|
|
6988
7153
|
gl.deleteBuffer(vbo);
|
|
6989
7154
|
gl.deleteBuffer(ibo);
|
|
6990
7155
|
}
|
|
7156
|
+
var IMAGE_QUAD_RING_SIZE = 64;
|
|
7157
|
+
var IMAGE_QUAD_RINGS = /* @__PURE__ */ new WeakMap();
|
|
7158
|
+
var IMAGE_QUAD_INDICES = new Uint32Array([0, 1, 2, 1, 3, 2]);
|
|
7159
|
+
var IMAGE_QUAD_STRIDE = 16;
|
|
7160
|
+
function imageQuadRing(gl, prog) {
|
|
7161
|
+
const existing = IMAGE_QUAD_RINGS.get(prog);
|
|
7162
|
+
if (existing) return existing;
|
|
7163
|
+
const aPosLoc = prog.attribute("a_position");
|
|
7164
|
+
const aUvLoc = prog.attribute("a_uv");
|
|
7165
|
+
const ibo = gl.createBuffer();
|
|
7166
|
+
if (!ibo) throw new Error("drawImage: createBuffer (IBO) returned null");
|
|
7167
|
+
const vaos = [];
|
|
7168
|
+
const vbos = [];
|
|
7169
|
+
for (let slot = 0; slot < IMAGE_QUAD_RING_SIZE; slot++) {
|
|
7170
|
+
const vao = gl.createVertexArray();
|
|
7171
|
+
const vbo = gl.createBuffer();
|
|
7172
|
+
if (!vao) throw new Error("drawImage: createVertexArray returned null");
|
|
7173
|
+
if (!vbo) throw new Error("drawImage: createBuffer returned null");
|
|
7174
|
+
gl.bindVertexArray(vao);
|
|
7175
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
7176
|
+
gl.bufferData(gl.ARRAY_BUFFER, 4 * IMAGE_QUAD_STRIDE, gl.DYNAMIC_DRAW);
|
|
7177
|
+
if (aPosLoc !== void 0) {
|
|
7178
|
+
gl.enableVertexAttribArray(aPosLoc);
|
|
7179
|
+
gl.vertexAttribPointer(aPosLoc, 2, gl.FLOAT, false, IMAGE_QUAD_STRIDE, 0);
|
|
7180
|
+
}
|
|
7181
|
+
if (aUvLoc !== void 0) {
|
|
7182
|
+
gl.enableVertexAttribArray(aUvLoc);
|
|
7183
|
+
gl.vertexAttribPointer(aUvLoc, 2, gl.FLOAT, false, IMAGE_QUAD_STRIDE, 8);
|
|
7184
|
+
}
|
|
7185
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
|
|
7186
|
+
if (slot === 0) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, IMAGE_QUAD_INDICES, gl.STATIC_DRAW);
|
|
7187
|
+
gl.bindVertexArray(null);
|
|
7188
|
+
vaos.push(vao);
|
|
7189
|
+
vbos.push(vbo);
|
|
7190
|
+
}
|
|
7191
|
+
const ring = { vaos, vbos, ibo, next: 0 };
|
|
7192
|
+
IMAGE_QUAD_RINGS.set(prog, ring);
|
|
7193
|
+
return ring;
|
|
7194
|
+
}
|
|
7195
|
+
function disposeImageQuads(gl, prog) {
|
|
7196
|
+
const ring = IMAGE_QUAD_RINGS.get(prog);
|
|
7197
|
+
if (!ring) return;
|
|
7198
|
+
for (const vao of ring.vaos) gl.deleteVertexArray(vao);
|
|
7199
|
+
for (const vbo of ring.vbos) gl.deleteBuffer(vbo);
|
|
7200
|
+
gl.deleteBuffer(ring.ibo);
|
|
7201
|
+
IMAGE_QUAD_RINGS.delete(prog);
|
|
7202
|
+
}
|
|
7203
|
+
var IMAGE_QUAD_VERTICES = new Float32Array(16);
|
|
6991
7204
|
function drawImage(ctx, cmd) {
|
|
6992
7205
|
ctx.imageCache.upload(cmd.image, cmd.image);
|
|
6993
7206
|
const gl = ctx.gl;
|
|
6994
|
-
|
|
7207
|
+
const prog = ctx.imageFill;
|
|
7208
|
+
gl.useProgram(prog.handle);
|
|
6995
7209
|
const x0 = cmd.x, y0 = cmd.y;
|
|
6996
7210
|
const x1 = cmd.x + cmd.w, y1 = cmd.y + cmd.h;
|
|
6997
|
-
const
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
const
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
gl.
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);
|
|
7023
|
-
const stride = 16;
|
|
7024
|
-
const aPosLoc = ctx.imageFill.attribute("a_position");
|
|
7025
|
-
const aUvLoc = ctx.imageFill.attribute("a_uv");
|
|
7026
|
-
if (aPosLoc !== void 0) {
|
|
7027
|
-
gl.enableVertexAttribArray(aPosLoc);
|
|
7028
|
-
gl.vertexAttribPointer(aPosLoc, 2, gl.FLOAT, false, stride, 0);
|
|
7029
|
-
}
|
|
7030
|
-
if (aUvLoc !== void 0) {
|
|
7031
|
-
gl.enableVertexAttribArray(aUvLoc);
|
|
7032
|
-
gl.vertexAttribPointer(aUvLoc, 2, gl.FLOAT, false, stride, 8);
|
|
7033
|
-
}
|
|
7034
|
-
const ibo = gl.createBuffer();
|
|
7035
|
-
if (!ibo) throw new Error("drawImage: createBuffer (IBO) returned null");
|
|
7036
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
|
|
7037
|
-
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.DYNAMIC_DRAW);
|
|
7038
|
-
setProjAndModel(ctx, ctx.imageFill);
|
|
7039
|
-
setColorMatrixUniforms(ctx, ctx.imageFill);
|
|
7211
|
+
const v = IMAGE_QUAD_VERTICES;
|
|
7212
|
+
v[0] = x0;
|
|
7213
|
+
v[1] = y0;
|
|
7214
|
+
v[2] = 0;
|
|
7215
|
+
v[3] = 0;
|
|
7216
|
+
v[4] = x1;
|
|
7217
|
+
v[5] = y0;
|
|
7218
|
+
v[6] = 1;
|
|
7219
|
+
v[7] = 0;
|
|
7220
|
+
v[8] = x0;
|
|
7221
|
+
v[9] = y1;
|
|
7222
|
+
v[10] = 0;
|
|
7223
|
+
v[11] = 1;
|
|
7224
|
+
v[12] = x1;
|
|
7225
|
+
v[13] = y1;
|
|
7226
|
+
v[14] = 1;
|
|
7227
|
+
v[15] = 1;
|
|
7228
|
+
const ring = imageQuadRing(gl, prog);
|
|
7229
|
+
const slot = ring.next;
|
|
7230
|
+
ring.next = (slot + 1) % IMAGE_QUAD_RING_SIZE;
|
|
7231
|
+
gl.bindVertexArray(ring.vaos[slot]);
|
|
7232
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, ring.vbos[slot]);
|
|
7233
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, 0, v);
|
|
7234
|
+
setProjAndModel(ctx, prog);
|
|
7235
|
+
setColorMatrixUniforms(ctx, prog);
|
|
7040
7236
|
ctx.imageCache.bind(cmd.image, 0);
|
|
7041
7237
|
gl.texParameteri(
|
|
7042
7238
|
gl.TEXTURE_2D,
|
|
7043
7239
|
gl.TEXTURE_MAG_FILTER,
|
|
7044
7240
|
cmd.sampling === "nearest" ? gl.NEAREST : gl.LINEAR
|
|
7045
7241
|
);
|
|
7046
|
-
gl.uniform1i(
|
|
7047
|
-
gl.uniform1f(
|
|
7048
|
-
|
|
7242
|
+
gl.uniform1i(prog.uniform("u_sampler"), 0);
|
|
7243
|
+
gl.uniform1f(prog.uniform("u_opacity"), cmd.opacity ?? 1);
|
|
7244
|
+
setAlphaUniform(ctx, prog, ctx.state.alpha);
|
|
7049
7245
|
applyClipTest(ctx);
|
|
7050
7246
|
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, 0);
|
|
7051
7247
|
gl.bindVertexArray(null);
|
|
7052
|
-
gl.deleteVertexArray(vao);
|
|
7053
|
-
gl.deleteBuffer(vbo);
|
|
7054
|
-
gl.deleteBuffer(ibo);
|
|
7055
7248
|
}
|
|
7056
7249
|
var CUSTOM_VERT_SRC = (
|
|
7057
7250
|
/* glsl */
|
|
@@ -7263,6 +7456,8 @@ var WeaselRenderer = class {
|
|
|
7263
7456
|
const program = new ShaderProgram(this.gl, vertSrc, fragSrc);
|
|
7264
7457
|
program.lookupUniforms([...CUSTOM_KIT_UNIFORMS, ...extractUniformNames(fragSrc)]);
|
|
7265
7458
|
program.lookupAttributes(CUSTOM_ATTRIBUTES);
|
|
7459
|
+
const previous = this.programRegistry.get(handle.id);
|
|
7460
|
+
if (previous) this.gl.deleteProgram(previous.handle);
|
|
7266
7461
|
this.programRegistry.set(handle.id, program);
|
|
7267
7462
|
}
|
|
7268
7463
|
applyViewport() {
|
|
@@ -7360,7 +7555,7 @@ var WeaselRenderer = class {
|
|
|
7360
7555
|
}
|
|
7361
7556
|
this.meshCache.freeTransient();
|
|
7362
7557
|
this.meshCache.drainPendingDeletes();
|
|
7363
|
-
for (const prog of [this.pathFill, this.pathFillVColor, this.textSdf, this.textSdfR8, this.imageFill, this.gradFill]) {
|
|
7558
|
+
for (const prog of [this.pathFill, this.pathFillVColor, this.textSdf, this.textSdfR8, this.imageFill, this.gradFill, this.patternFill]) {
|
|
7364
7559
|
gl.deleteProgram(prog.handle);
|
|
7365
7560
|
}
|
|
7366
7561
|
for (const prog of this.programRegistry.values()) {
|
|
@@ -7371,6 +7566,7 @@ var WeaselRenderer = class {
|
|
|
7371
7566
|
this.gradRampCache.free();
|
|
7372
7567
|
if (this.quadVbo) gl.deleteBuffer(this.quadVbo);
|
|
7373
7568
|
if (this.quadIbo) gl.deleteBuffer(this.quadIbo);
|
|
7569
|
+
disposeImageQuads(gl, this.imageFill);
|
|
7374
7570
|
this.solidBatch.dispose();
|
|
7375
7571
|
}
|
|
7376
7572
|
/**
|
|
@@ -7386,6 +7582,7 @@ var WeaselRenderer = class {
|
|
|
7386
7582
|
const gl = this.gl;
|
|
7387
7583
|
this.meshCache.drainPendingDeletes();
|
|
7388
7584
|
resetBakeBudget(this.bakeBudget);
|
|
7585
|
+
this.groupState.reset();
|
|
7389
7586
|
gl.stencilMask(255);
|
|
7390
7587
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
|
|
7391
7588
|
const ctx = {
|
|
@@ -10955,7 +11152,7 @@ var reorderBackwardAction = {
|
|
|
10955
11152
|
}
|
|
10956
11153
|
],
|
|
10957
11154
|
eligible: { capability: "edits-page" },
|
|
10958
|
-
requires: ["selection", "scene"],
|
|
11155
|
+
requires: ["selection", "scene", "applyOps"],
|
|
10959
11156
|
invoker: {
|
|
10960
11157
|
timing: "immediate",
|
|
10961
11158
|
run: (deps, params) => {
|
|
@@ -11095,6 +11292,7 @@ function makeAlignAction(edge) {
|
|
|
11095
11292
|
icon: ICON_FOR[edge],
|
|
11096
11293
|
group: "align",
|
|
11097
11294
|
eligible: { capability: "transforms-selection" },
|
|
11295
|
+
requires: ["selection", "scene"],
|
|
11098
11296
|
// No default keybindings — six edges/centers don't fit a clean default
|
|
11099
11297
|
// chord set. Wire bindings explicitly via the actions registry override map.
|
|
11100
11298
|
invoker: {
|
|
@@ -11106,7 +11304,14 @@ function makeAlignAction(edge) {
|
|
|
11106
11304
|
alignSelection(selection, scene, edge);
|
|
11107
11305
|
}
|
|
11108
11306
|
},
|
|
11109
|
-
|
|
11307
|
+
// Deps-aware, matching `alignSelection`'s own `ids.length < 2` guard: a
|
|
11308
|
+
// constant disabled reason greys the entry out forever (see
|
|
11309
|
+
// `requiresSelection`).
|
|
11310
|
+
enabled: (deps) => {
|
|
11311
|
+
const selection = deps?.selection;
|
|
11312
|
+
const count = selection?.get().length ?? 0;
|
|
11313
|
+
return count >= 2 ? true : ActionDisabledReason.SelectionRequired;
|
|
11314
|
+
}
|
|
11110
11315
|
};
|
|
11111
11316
|
}
|
|
11112
11317
|
var alignLeftAction = makeAlignAction("left");
|
|
@@ -11187,6 +11392,7 @@ function makeDistributeAction(axis) {
|
|
|
11187
11392
|
icon: ICON_FOR2[axis],
|
|
11188
11393
|
group: "distribute",
|
|
11189
11394
|
eligible: { capability: "transforms-selection" },
|
|
11395
|
+
requires: ["selection", "scene"],
|
|
11190
11396
|
// No default keybindings. Wire bindings explicitly via the actions registry.
|
|
11191
11397
|
invoker: {
|
|
11192
11398
|
timing: "immediate",
|
|
@@ -11197,7 +11403,14 @@ function makeDistributeAction(axis) {
|
|
|
11197
11403
|
distributeSelection(selection, scene, axis);
|
|
11198
11404
|
}
|
|
11199
11405
|
},
|
|
11200
|
-
|
|
11406
|
+
// Deps-aware, matching `distributeSelection`'s own `ids.length < 3` guard:
|
|
11407
|
+
// a constant disabled reason greys the entry out forever (see
|
|
11408
|
+
// `requiresSelection`).
|
|
11409
|
+
enabled: (deps) => {
|
|
11410
|
+
const selection = deps?.selection;
|
|
11411
|
+
const count = selection?.get().length ?? 0;
|
|
11412
|
+
return count >= 3 ? true : ActionDisabledReason.SelectionRequired;
|
|
11413
|
+
}
|
|
11201
11414
|
};
|
|
11202
11415
|
}
|
|
11203
11416
|
var distributeHorizontalAction = makeDistributeAction("x");
|
|
@@ -11279,7 +11492,91 @@ function pathToMultiPolygon(path, opts = {}) {
|
|
|
11279
11492
|
}
|
|
11280
11493
|
finalizeCurrent();
|
|
11281
11494
|
if (rings.length === 0) return [];
|
|
11282
|
-
return rings.
|
|
11495
|
+
return groupRings(rings, path.fillRule);
|
|
11496
|
+
}
|
|
11497
|
+
function ringSignedArea(ring) {
|
|
11498
|
+
let a = 0;
|
|
11499
|
+
for (let i = 0, n = ring.length - 1; i < n; i++) {
|
|
11500
|
+
a += ring[i][0] * ring[i + 1][1] - ring[i + 1][0] * ring[i][1];
|
|
11501
|
+
}
|
|
11502
|
+
return a * 0.5;
|
|
11503
|
+
}
|
|
11504
|
+
function ringBox(ring) {
|
|
11505
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
11506
|
+
for (const [x, y] of ring) {
|
|
11507
|
+
if (x < minX) minX = x;
|
|
11508
|
+
if (x > maxX) maxX = x;
|
|
11509
|
+
if (y < minY) minY = y;
|
|
11510
|
+
if (y > maxY) maxY = y;
|
|
11511
|
+
}
|
|
11512
|
+
return [minX, minY, maxX, maxY];
|
|
11513
|
+
}
|
|
11514
|
+
function pointInRing(ring, px, py) {
|
|
11515
|
+
let inside = false;
|
|
11516
|
+
for (let i = 0, n = ring.length - 1; i < n; i++) {
|
|
11517
|
+
const [ax, ay] = ring[i];
|
|
11518
|
+
const [bx, by] = ring[i + 1];
|
|
11519
|
+
if (ay > py !== by > py && px < (bx - ax) * (py - ay) / (by - ay) + ax) {
|
|
11520
|
+
inside = !inside;
|
|
11521
|
+
}
|
|
11522
|
+
}
|
|
11523
|
+
return inside;
|
|
11524
|
+
}
|
|
11525
|
+
function ringContains(outer, outerBox, inner, innerBox) {
|
|
11526
|
+
if (innerBox[0] < outerBox[0] || innerBox[1] < outerBox[1] || innerBox[2] > outerBox[2] || innerBox[3] > outerBox[3]) return false;
|
|
11527
|
+
const n = inner.length - 1;
|
|
11528
|
+
let votes = 0;
|
|
11529
|
+
for (const k of [0, Math.floor(n / 3), Math.floor(2 * n / 3)]) {
|
|
11530
|
+
if (pointInRing(outer, inner[k][0], inner[k][1])) votes++;
|
|
11531
|
+
}
|
|
11532
|
+
return votes >= 2;
|
|
11533
|
+
}
|
|
11534
|
+
function groupRings(rings, fillRule) {
|
|
11535
|
+
const n = rings.length;
|
|
11536
|
+
if (n === 1) return [[rings[0]]];
|
|
11537
|
+
const boxes = rings.map(ringBox);
|
|
11538
|
+
const orient = rings.map((r) => ringSignedArea(r) >= 0 ? 1 : -1);
|
|
11539
|
+
const parent = new Array(n).fill(-1);
|
|
11540
|
+
const children = rings.map(() => []);
|
|
11541
|
+
for (let i = 0; i < n; i++) {
|
|
11542
|
+
let best = -1;
|
|
11543
|
+
let bestArea = Infinity;
|
|
11544
|
+
for (let j = 0; j < n; j++) {
|
|
11545
|
+
if (i === j) continue;
|
|
11546
|
+
if (!ringContains(rings[j], boxes[j], rings[i], boxes[i])) continue;
|
|
11547
|
+
const area = (boxes[j][2] - boxes[j][0]) * (boxes[j][3] - boxes[j][1]);
|
|
11548
|
+
if (area < bestArea) {
|
|
11549
|
+
bestArea = area;
|
|
11550
|
+
best = j;
|
|
11551
|
+
}
|
|
11552
|
+
}
|
|
11553
|
+
parent[i] = best;
|
|
11554
|
+
}
|
|
11555
|
+
for (let i = 0; i < n; i++) if (parent[i] >= 0) children[parent[i]].push(i);
|
|
11556
|
+
const filled = new Array(n);
|
|
11557
|
+
for (let i = 0; i < n; i++) {
|
|
11558
|
+
let depth = 0;
|
|
11559
|
+
let winding = 0;
|
|
11560
|
+
for (let a = i; a >= 0; a = parent[a]) {
|
|
11561
|
+
winding += orient[a];
|
|
11562
|
+
if (a !== i) depth++;
|
|
11563
|
+
}
|
|
11564
|
+
filled[i] = fillRule === "evenodd" ? depth % 2 === 0 : winding !== 0;
|
|
11565
|
+
}
|
|
11566
|
+
const out = [];
|
|
11567
|
+
for (let i = 0; i < n; i++) {
|
|
11568
|
+
if (!filled[i]) continue;
|
|
11569
|
+
if (parent[i] >= 0 && filled[parent[i]]) continue;
|
|
11570
|
+
const polygon = [rings[i]];
|
|
11571
|
+
const queue = [...children[i]];
|
|
11572
|
+
while (queue.length > 0) {
|
|
11573
|
+
const c = queue.pop();
|
|
11574
|
+
if (filled[c]) queue.push(...children[c]);
|
|
11575
|
+
else polygon.push(rings[c]);
|
|
11576
|
+
}
|
|
11577
|
+
out.push(polygon);
|
|
11578
|
+
}
|
|
11579
|
+
return out;
|
|
11283
11580
|
}
|
|
11284
11581
|
function multiPolygonToPath(mp) {
|
|
11285
11582
|
let nCmds = 0;
|
|
@@ -11592,6 +11889,7 @@ function makePathfinderAction(op) {
|
|
|
11592
11889
|
icon: ICON_FOR3[op],
|
|
11593
11890
|
group: "pathfinder",
|
|
11594
11891
|
eligible: { capability: "creates-shapes" },
|
|
11892
|
+
requires: ["selection", "booleansAdapter"],
|
|
11595
11893
|
// No default keybindings — there's no industry-standard chord set for
|
|
11596
11894
|
// boolean ops. Wire bindings explicitly via the actions registry override map.
|
|
11597
11895
|
invoker: {
|
|
@@ -13884,10 +14182,11 @@ function createDispatcher(opts) {
|
|
|
13884
14182
|
uiOngoingByAction.set(actionId, gestureId);
|
|
13885
14183
|
notify2();
|
|
13886
14184
|
let ended = false;
|
|
14185
|
+
const live = () => !ended && inFlightHandles.get(gestureId) === handle;
|
|
13887
14186
|
return {
|
|
13888
14187
|
gestureId,
|
|
13889
14188
|
update(nextParams) {
|
|
13890
|
-
if (
|
|
14189
|
+
if (!live()) return;
|
|
13891
14190
|
if (!handle.onMove) return;
|
|
13892
14191
|
try {
|
|
13893
14192
|
handle.onMove(buildUiInvocationCtx(deps, nextParams));
|
|
@@ -13897,7 +14196,10 @@ function createDispatcher(opts) {
|
|
|
13897
14196
|
notify2();
|
|
13898
14197
|
},
|
|
13899
14198
|
end(reason) {
|
|
13900
|
-
if (
|
|
14199
|
+
if (!live()) {
|
|
14200
|
+
ended = true;
|
|
14201
|
+
return;
|
|
14202
|
+
}
|
|
13901
14203
|
ended = true;
|
|
13902
14204
|
if (handle.onEnd) {
|
|
13903
14205
|
try {
|
|
@@ -15111,6 +15413,7 @@ function useTools(opts) {
|
|
|
15111
15413
|
);
|
|
15112
15414
|
const active = contributions.focused;
|
|
15113
15415
|
const getActiveOverlays = contributions.overlays;
|
|
15416
|
+
const registryKey = Object.keys(slotted.registry).sort().join("|") + "#" + slotted.ambient.map((t) => t.id).join("|");
|
|
15114
15417
|
return useMemo(
|
|
15115
15418
|
() => ({
|
|
15116
15419
|
active,
|
|
@@ -15123,7 +15426,7 @@ function useTools(opts) {
|
|
|
15123
15426
|
has,
|
|
15124
15427
|
getActiveOverlays
|
|
15125
15428
|
}),
|
|
15126
|
-
[active, setActive, hotkeyEngaged, engageHotkey, disengageHotkey, has, getActiveOverlays]
|
|
15429
|
+
[active, setActive, hotkeyEngaged, engageHotkey, disengageHotkey, has, getActiveOverlays, registryKey]
|
|
15127
15430
|
);
|
|
15128
15431
|
}
|
|
15129
15432
|
var TOOL_ACTIVATE_ID = "tool.activate";
|
|
@@ -16514,8 +16817,17 @@ function composeAffordanceLayer(id, label, affordances) {
|
|
|
16514
16817
|
// `buildAffordanceAt` share one implementation rather than two that can
|
|
16515
16818
|
// drift. This wrapper lifts the region's declared cursor and claim onto
|
|
16516
16819
|
// the binding, the way `buildAffordanceAt` lifts them onto `AffordanceHit`.
|
|
16517
|
-
hitTest: (wx, wy,
|
|
16518
|
-
const
|
|
16820
|
+
hitTest: (wx, wy, data, view, _dims, isVisible) => {
|
|
16821
|
+
const state = asChromeState(data);
|
|
16822
|
+
if (!state) return null;
|
|
16823
|
+
const hit = hitAffordanceRegions(
|
|
16824
|
+
affordances,
|
|
16825
|
+
wx,
|
|
16826
|
+
wy,
|
|
16827
|
+
state,
|
|
16828
|
+
view,
|
|
16829
|
+
isVisible ?? asIsVisible(data) ?? void 0
|
|
16830
|
+
);
|
|
16519
16831
|
if (!hit) return null;
|
|
16520
16832
|
const { cursor, strength, claimedKinds } = hit.region;
|
|
16521
16833
|
return {
|
|
@@ -17118,6 +17430,10 @@ function usePenTool(options) {
|
|
|
17118
17430
|
onEnd: (endCtx, reason) => {
|
|
17119
17431
|
const se = s();
|
|
17120
17432
|
if (reason === "cancel") {
|
|
17433
|
+
if (se.current && se.draggingHandleAt === se.current.anchors.length - 1) {
|
|
17434
|
+
se.current.anchors.pop();
|
|
17435
|
+
if (se.current.anchors.length === 0) se.current = null;
|
|
17436
|
+
}
|
|
17121
17437
|
se.draggingHandleAt = null;
|
|
17122
17438
|
forceRenderRef.current();
|
|
17123
17439
|
return;
|
|
@@ -18696,7 +19012,6 @@ function CanvasInner(props, ref) {
|
|
|
18696
19012
|
shaders,
|
|
18697
19013
|
previewIdsExtra,
|
|
18698
19014
|
previewPoseExtra,
|
|
18699
|
-
previewBoundsExtra,
|
|
18700
19015
|
gestureSource,
|
|
18701
19016
|
viewport,
|
|
18702
19017
|
backgroundFill,
|
|
@@ -18722,6 +19037,7 @@ function CanvasInner(props, ref) {
|
|
|
18722
19037
|
debugSinkRefForCtx.current = debugSink;
|
|
18723
19038
|
const adapter = adapterProp;
|
|
18724
19039
|
const canvasRef = useRef(null);
|
|
19040
|
+
const helpersForLayersRef = useRef(null);
|
|
18725
19041
|
const dimsRef = useRef({ width, height });
|
|
18726
19042
|
dimsRef.current = { width, height };
|
|
18727
19043
|
const getIsVisibleRef = useRef(getIsVisible);
|
|
@@ -18744,7 +19060,7 @@ function CanvasInner(props, ref) {
|
|
|
18744
19060
|
const isVisible = getIsVisibleRef.current?.() ?? alwaysVisible;
|
|
18745
19061
|
for (const layer of layers2) {
|
|
18746
19062
|
if (!layer.hitTest) continue;
|
|
18747
|
-
const hit = layer.hitTest(worldX, worldY,
|
|
19063
|
+
const hit = layer.hitTest(worldX, worldY, helpersForLayersRef.current, view, dims, isVisible);
|
|
18748
19064
|
if (hit) return { layerId: layer.id, hit };
|
|
18749
19065
|
}
|
|
18750
19066
|
return null;
|
|
@@ -18899,8 +19215,8 @@ function CanvasInner(props, ref) {
|
|
|
18899
19215
|
};
|
|
18900
19216
|
const selectedIdsForWiring = effectiveSelection.current;
|
|
18901
19217
|
const multiActive2 = selectedIdsForWiring.length > 1;
|
|
18902
|
-
const previewExtraRef = useRef({ previewPoseExtra
|
|
18903
|
-
previewExtraRef.current = { previewPoseExtra
|
|
19218
|
+
const previewExtraRef = useRef({ previewPoseExtra });
|
|
19219
|
+
previewExtraRef.current = { previewPoseExtra };
|
|
18904
19220
|
const effectiveBoundsOf = useMemo(() => {
|
|
18905
19221
|
return boundsOf2 ?? baseBoundsOf;
|
|
18906
19222
|
}, [boundsOf2, baseBoundsOf]);
|
|
@@ -18919,10 +19235,6 @@ function CanvasInner(props, ref) {
|
|
|
18919
19235
|
if (p != null) return geometry.getBounds(p);
|
|
18920
19236
|
}
|
|
18921
19237
|
const extras = previewExtraRef.current;
|
|
18922
|
-
if (extras.previewBoundsExtra) {
|
|
18923
|
-
const b = extras.previewBoundsExtra(id);
|
|
18924
|
-
if (b) return b;
|
|
18925
|
-
}
|
|
18926
19238
|
if (extras.previewPoseExtra) {
|
|
18927
19239
|
const p = extras.previewPoseExtra(id);
|
|
18928
19240
|
if (p != null) return geometry.getBounds(p);
|
|
@@ -18963,10 +19275,6 @@ function CanvasInner(props, ref) {
|
|
|
18963
19275
|
const p = firstPreviewPose(tools, id);
|
|
18964
19276
|
if (p != null) return geometry.getBounds(p);
|
|
18965
19277
|
}
|
|
18966
|
-
if (previewBoundsExtra) {
|
|
18967
|
-
const b = previewBoundsExtra(id);
|
|
18968
|
-
if (b) return b;
|
|
18969
|
-
}
|
|
18970
19278
|
if (previewPoseExtra) {
|
|
18971
19279
|
const p = previewPoseExtra(id);
|
|
18972
19280
|
if (p != null) return geometry.getBounds(p);
|
|
@@ -19002,6 +19310,7 @@ function CanvasInner(props, ref) {
|
|
|
19002
19310
|
getDebug: () => debugSink,
|
|
19003
19311
|
getIsVisible: () => getIsVisibleRef.current?.() ?? alwaysVisible
|
|
19004
19312
|
};
|
|
19313
|
+
helpersForLayersRef.current = helpersForLayers;
|
|
19005
19314
|
if (helpersRef) helpersRef.current = helpersForLayers;
|
|
19006
19315
|
const pointerDownRef = useRef(false);
|
|
19007
19316
|
const handlePointerDown = (e) => {
|
|
@@ -19183,6 +19492,11 @@ function CanvasInner(props, ref) {
|
|
|
19183
19492
|
);
|
|
19184
19493
|
renderer.render(commands, viewToMat3(effectiveView));
|
|
19185
19494
|
}, [layersWithDebug, width, height, effectiveView, debugSink, redrawNonce, dprProp]);
|
|
19495
|
+
useEffect(() => () => {
|
|
19496
|
+
glRendererRef.current?.dispose();
|
|
19497
|
+
glRendererRef.current = null;
|
|
19498
|
+
lastResizeRef.current = null;
|
|
19499
|
+
}, []);
|
|
19186
19500
|
const shaderIdKey = shaders?.map((h) => h.id).join("|") ?? "";
|
|
19187
19501
|
useEffect(() => {
|
|
19188
19502
|
const renderer = glRendererRef.current;
|
|
@@ -20611,6 +20925,89 @@ function poseContainsRotated(pose, wx, wy, tolerance) {
|
|
|
20611
20925
|
}
|
|
20612
20926
|
return poseContains(pose, wx, wy, tolerance);
|
|
20613
20927
|
}
|
|
20928
|
+
function hiddenLayerIds(layers) {
|
|
20929
|
+
const out = /* @__PURE__ */ new Set();
|
|
20930
|
+
for (const layer of layers ?? []) {
|
|
20931
|
+
if (layer.visible === false) out.add(layer.id);
|
|
20932
|
+
}
|
|
20933
|
+
return out;
|
|
20934
|
+
}
|
|
20935
|
+
function hitTestArea(scene, bounds) {
|
|
20936
|
+
const { x, y, width: w, height: h } = bounds;
|
|
20937
|
+
const area = [x, y, x + w, y, x + w, y + h, x, y + h];
|
|
20938
|
+
return hitTestAreaPolygon(scene, area, { x, y, width: w, height: h }, true);
|
|
20939
|
+
}
|
|
20940
|
+
function hitTestAreaPolygon(scene, area, areaBounds, areaIsRect = false) {
|
|
20941
|
+
const ab = areaBounds ?? boundsOf(area);
|
|
20942
|
+
if (!ab) return [];
|
|
20943
|
+
const hits = [];
|
|
20944
|
+
const hidden = hiddenLayerIds(scene.layers);
|
|
20945
|
+
const order = scene.renderOrderNodes();
|
|
20946
|
+
for (let i = 0; i < order.length; i++) {
|
|
20947
|
+
const node = order[i];
|
|
20948
|
+
if (node.kind === "container") continue;
|
|
20949
|
+
if (hidden.size > 0 && hidden.has(node.layer)) continue;
|
|
20950
|
+
const pose = node.pose;
|
|
20951
|
+
const silhouette = pose !== null && typeof pose === "object" && pose.kind === "polygon";
|
|
20952
|
+
const b = silhouette ? nodeMemo(node, "aabb", pose, () => aabbOfPose(pose)) : aabbOfPose(pose);
|
|
20953
|
+
if (!Number.isFinite(b.x) || !Number.isFinite(b.y) || !Number.isFinite(b.width) || !Number.isFinite(b.height)) {
|
|
20954
|
+
continue;
|
|
20955
|
+
}
|
|
20956
|
+
if (b.x >= ab.x + ab.width || b.x + b.width <= ab.x || b.y >= ab.y + ab.height || b.y + b.height <= ab.y) {
|
|
20957
|
+
continue;
|
|
20958
|
+
}
|
|
20959
|
+
if (areaIsRect && b.x >= ab.x && b.y >= ab.y && b.x + b.width <= ab.x + ab.width && b.y + b.height <= ab.y + ab.height) {
|
|
20960
|
+
hits.push(node.id);
|
|
20961
|
+
continue;
|
|
20962
|
+
}
|
|
20963
|
+
if (silhouette) {
|
|
20964
|
+
if (silhouetteOverlapsArea(pose.coords, area)) {
|
|
20965
|
+
hits.push(node.id);
|
|
20966
|
+
}
|
|
20967
|
+
continue;
|
|
20968
|
+
}
|
|
20969
|
+
const drawn = findShapeSilhouette(node, pose);
|
|
20970
|
+
if (drawn?.kind === "polygon") {
|
|
20971
|
+
if (silhouetteOverlapsArea(drawn.coords, area)) hits.push(node.id);
|
|
20972
|
+
continue;
|
|
20973
|
+
}
|
|
20974
|
+
hits.push(node.id);
|
|
20975
|
+
}
|
|
20976
|
+
return hits;
|
|
20977
|
+
}
|
|
20978
|
+
function silhouetteOverlapsArea(sil, area) {
|
|
20979
|
+
const ns = sil.length >> 1;
|
|
20980
|
+
const na = area.length >> 1;
|
|
20981
|
+
if (ns < 1 || na < 3) return false;
|
|
20982
|
+
for (let i = 0; i < ns; i++) {
|
|
20983
|
+
if (pointInPolygon(area, sil[i * 2], sil[i * 2 + 1])) return true;
|
|
20984
|
+
}
|
|
20985
|
+
for (let i = 0; i < na; i++) {
|
|
20986
|
+
if (pointInPolygon(sil, area[i * 2], area[i * 2 + 1])) return true;
|
|
20987
|
+
}
|
|
20988
|
+
for (let i = 0, j = ns - 1; i < ns; j = i++) {
|
|
20989
|
+
const ax = sil[j * 2], ay = sil[j * 2 + 1];
|
|
20990
|
+
const bx = sil[i * 2], by = sil[i * 2 + 1];
|
|
20991
|
+
for (let k = 0, l = na - 1; k < na; l = k++) {
|
|
20992
|
+
const cx = area[l * 2], cy = area[l * 2 + 1];
|
|
20993
|
+
const dx = area[k * 2], dy = area[k * 2 + 1];
|
|
20994
|
+
if (segmentsCross(ax, ay, bx, by, cx, cy, dx, dy)) return true;
|
|
20995
|
+
}
|
|
20996
|
+
}
|
|
20997
|
+
return false;
|
|
20998
|
+
}
|
|
20999
|
+
function boundsOf(coords) {
|
|
21000
|
+
if (coords.length < 2) return null;
|
|
21001
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
21002
|
+
for (let i = 0; i + 1 < coords.length; i += 2) {
|
|
21003
|
+
const x = coords[i], y = coords[i + 1];
|
|
21004
|
+
if (x < minX) minX = x;
|
|
21005
|
+
if (y < minY) minY = y;
|
|
21006
|
+
if (x > maxX) maxX = x;
|
|
21007
|
+
if (y > maxY) maxY = y;
|
|
21008
|
+
}
|
|
21009
|
+
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
21010
|
+
}
|
|
20614
21011
|
var DEFAULT_PICK_TOLERANCE_PX = 4;
|
|
20615
21012
|
function useSceneSelectTool(args) {
|
|
20616
21013
|
const { scene, selection, geometry, selectTool: opts, insertTool, layouts, getView } = args;
|
|
@@ -20708,7 +21105,9 @@ function useSceneSelectTool(args) {
|
|
|
20708
21105
|
}
|
|
20709
21106
|
const tolerance = pickTolerancePx / meanScale(getView?.()?.scale ?? { x: 1, y: 1 });
|
|
20710
21107
|
const out = [];
|
|
21108
|
+
const hidden = hiddenLayerIds(scene.layers);
|
|
20711
21109
|
for (const n of scene.renderOrderNodes()) {
|
|
21110
|
+
if (hidden.size > 0 && hidden.has(n.layer)) continue;
|
|
20712
21111
|
if (!poseContainsRotated(n.pose, wx, wy, tolerance)) continue;
|
|
20713
21112
|
if (shapePicking && !shapeCoversPoint(n, n.pose, wx, wy, { tolerance })) continue;
|
|
20714
21113
|
out.push(n.id);
|
|
@@ -21592,8 +21991,10 @@ function createPathAnchorAffordances(getAnchorState, opts = {}) {
|
|
|
21592
21991
|
const anchors = {
|
|
21593
21992
|
id: PATH_ANCHOR_CHROME_ID,
|
|
21594
21993
|
regions(state) {
|
|
21994
|
+
const editingId = getAnchorState()?.editingId ?? null;
|
|
21595
21995
|
const out = [];
|
|
21596
21996
|
for (const { id, path } of editablePaths(state)) {
|
|
21997
|
+
if (editingId !== null && id !== editingId) continue;
|
|
21597
21998
|
for (const a of enumerateAnchors(path)) {
|
|
21598
21999
|
out.push(point(
|
|
21599
22000
|
`${id}:anchor:${a.anchorIndex}`,
|
|
@@ -21848,80 +22249,6 @@ function DepRegistryProviderIfRoot({ children }) {
|
|
|
21848
22249
|
if (parent) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
21849
22250
|
return /* @__PURE__ */ jsx(DepRegistryProvider, { children });
|
|
21850
22251
|
}
|
|
21851
|
-
function hitTestArea(scene, bounds) {
|
|
21852
|
-
const { x, y, width: w, height: h } = bounds;
|
|
21853
|
-
const area = [x, y, x + w, y, x + w, y + h, x, y + h];
|
|
21854
|
-
return hitTestAreaPolygon(scene, area, { x, y, width: w, height: h }, true);
|
|
21855
|
-
}
|
|
21856
|
-
function hitTestAreaPolygon(scene, area, areaBounds, areaIsRect = false) {
|
|
21857
|
-
const ab = areaBounds ?? boundsOf(area);
|
|
21858
|
-
if (!ab) return [];
|
|
21859
|
-
const hits = [];
|
|
21860
|
-
const order = scene.renderOrderNodes();
|
|
21861
|
-
for (let i = 0; i < order.length; i++) {
|
|
21862
|
-
const node = order[i];
|
|
21863
|
-
if (node.kind === "container") continue;
|
|
21864
|
-
const pose = node.pose;
|
|
21865
|
-
const silhouette = pose !== null && typeof pose === "object" && pose.kind === "polygon";
|
|
21866
|
-
const b = silhouette ? nodeMemo(node, "aabb", pose, () => aabbOfPose(pose)) : aabbOfPose(pose);
|
|
21867
|
-
if (!Number.isFinite(b.x) || !Number.isFinite(b.y) || !Number.isFinite(b.width) || !Number.isFinite(b.height)) {
|
|
21868
|
-
continue;
|
|
21869
|
-
}
|
|
21870
|
-
if (b.x >= ab.x + ab.width || b.x + b.width <= ab.x || b.y >= ab.y + ab.height || b.y + b.height <= ab.y) {
|
|
21871
|
-
continue;
|
|
21872
|
-
}
|
|
21873
|
-
if (areaIsRect && b.x >= ab.x && b.y >= ab.y && b.x + b.width <= ab.x + ab.width && b.y + b.height <= ab.y + ab.height) {
|
|
21874
|
-
hits.push(node.id);
|
|
21875
|
-
continue;
|
|
21876
|
-
}
|
|
21877
|
-
if (silhouette) {
|
|
21878
|
-
if (silhouetteOverlapsArea(pose.coords, area)) {
|
|
21879
|
-
hits.push(node.id);
|
|
21880
|
-
}
|
|
21881
|
-
continue;
|
|
21882
|
-
}
|
|
21883
|
-
const drawn = findShapeSilhouette(node, pose);
|
|
21884
|
-
if (drawn?.kind === "polygon") {
|
|
21885
|
-
if (silhouetteOverlapsArea(drawn.coords, area)) hits.push(node.id);
|
|
21886
|
-
continue;
|
|
21887
|
-
}
|
|
21888
|
-
hits.push(node.id);
|
|
21889
|
-
}
|
|
21890
|
-
return hits;
|
|
21891
|
-
}
|
|
21892
|
-
function silhouetteOverlapsArea(sil, area) {
|
|
21893
|
-
const ns = sil.length >> 1;
|
|
21894
|
-
const na = area.length >> 1;
|
|
21895
|
-
if (ns < 1 || na < 3) return false;
|
|
21896
|
-
for (let i = 0; i < ns; i++) {
|
|
21897
|
-
if (pointInPolygon(area, sil[i * 2], sil[i * 2 + 1])) return true;
|
|
21898
|
-
}
|
|
21899
|
-
for (let i = 0; i < na; i++) {
|
|
21900
|
-
if (pointInPolygon(sil, area[i * 2], area[i * 2 + 1])) return true;
|
|
21901
|
-
}
|
|
21902
|
-
for (let i = 0, j = ns - 1; i < ns; j = i++) {
|
|
21903
|
-
const ax = sil[j * 2], ay = sil[j * 2 + 1];
|
|
21904
|
-
const bx = sil[i * 2], by = sil[i * 2 + 1];
|
|
21905
|
-
for (let k = 0, l = na - 1; k < na; l = k++) {
|
|
21906
|
-
const cx = area[l * 2], cy = area[l * 2 + 1];
|
|
21907
|
-
const dx = area[k * 2], dy = area[k * 2 + 1];
|
|
21908
|
-
if (segmentsCross(ax, ay, bx, by, cx, cy, dx, dy)) return true;
|
|
21909
|
-
}
|
|
21910
|
-
}
|
|
21911
|
-
return false;
|
|
21912
|
-
}
|
|
21913
|
-
function boundsOf(coords) {
|
|
21914
|
-
if (coords.length < 2) return null;
|
|
21915
|
-
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
21916
|
-
for (let i = 0; i + 1 < coords.length; i += 2) {
|
|
21917
|
-
const x = coords[i], y = coords[i + 1];
|
|
21918
|
-
if (x < minX) minX = x;
|
|
21919
|
-
if (y < minY) minY = y;
|
|
21920
|
-
if (x > maxX) maxX = x;
|
|
21921
|
-
if (y > maxY) maxY = y;
|
|
21922
|
-
}
|
|
21923
|
-
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
21924
|
-
}
|
|
21925
22252
|
function useViewDepSource(currentViewRef, onViewChange, recenter, hostSize) {
|
|
21926
22253
|
const viewApiRef = useRef({
|
|
21927
22254
|
get: () => currentViewRef.current,
|
|
@@ -22693,6 +23020,7 @@ function useActionsPropResolver(actions) {
|
|
|
22693
23020
|
}
|
|
22694
23021
|
if (!prop) return;
|
|
22695
23022
|
const unregisters = [];
|
|
23023
|
+
const restores = [];
|
|
22696
23024
|
const warnedIds = /* @__PURE__ */ new Set();
|
|
22697
23025
|
for (const [slotId, entry] of Object.entries(prop)) {
|
|
22698
23026
|
if (entry === null) {
|
|
@@ -22720,10 +23048,14 @@ function useActionsPropResolver(actions) {
|
|
|
22720
23048
|
}
|
|
22721
23049
|
const { id: _drop, ...rest } = entry;
|
|
22722
23050
|
const merged = { ...existing, ...rest };
|
|
23051
|
+
restores.push(() => {
|
|
23052
|
+
reg.register(existing);
|
|
23053
|
+
});
|
|
22723
23054
|
unregisters.push(reg.register(merged));
|
|
22724
23055
|
}
|
|
22725
23056
|
return () => {
|
|
22726
23057
|
for (const u of unregisters) u();
|
|
23058
|
+
for (const r of restores) r();
|
|
22727
23059
|
};
|
|
22728
23060
|
}, [reg, actions]);
|
|
22729
23061
|
}
|
|
@@ -24475,5 +24807,5 @@ function oklchToOklab(L, C, h) {
|
|
|
24475
24807
|
}
|
|
24476
24808
|
|
|
24477
24809
|
export { FALLBACK_FIT_VIEW, MinimapCanvas, SceneViewCanvas, UnknownIcon, buildSceneViewCommands, computeFitView2, computeIndicatorCommand, eligibleContribution, evaluateEnabled, oklabToSrgbU8, oklchToOklab, renderSceneToCanvas, rgbaToHex, useActionsRegistry, useOptionalDepRegistry };
|
|
24478
|
-
//# sourceMappingURL=chunk-
|
|
24479
|
-
//# sourceMappingURL=chunk-
|
|
24810
|
+
//# sourceMappingURL=chunk-DWV7SFKR.js.map
|
|
24811
|
+
//# sourceMappingURL=chunk-DWV7SFKR.js.map
|