@weasel-js/labkit 1.4.0 → 1.4.2
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/README.md +8 -0
- package/dist/_dts/{CanvasStackContext-D6M0o8cQ.d.ts → CanvasStackContext-kjILVnPj.d.ts} +1 -1
- package/dist/_dts/PrefsForm.d-CgxUequc.d.ts +20 -0
- package/dist/_dts/{frac-QS7XzvpG.d.ts → frac-A4R6v4ld.d.ts} +36 -13
- package/dist/_dts/{index-B2X21G1c.d.ts → index-CsU9WhjM.d.ts} +90 -30
- package/dist/_dts/{types-ChVJJHvk.d.ts → types-BbXpvQa8.d.ts} +20 -1
- package/dist/_dts/{types-C1Zw7s5P.d.ts → types-lg4TSCb2.d.ts} +2 -1
- package/dist/_dts/{useTrialState-Cdm13fvl.d.ts → useTrialState-DKjqpv20.d.ts} +5 -1
- package/dist/_dts/weasel-canvas-FJTFi3ZZ.d.ts +5041 -0
- package/dist/canvas/index.d.ts +16 -16
- package/dist/canvas/index.js +2 -2
- package/dist/chrome/index.d.ts +15 -9
- package/dist/chrome/index.js +5 -5
- package/dist/{chunk-7VW3S44V.js → chunk-54ZWZ5FQ.js} +908 -301
- package/dist/chunk-54ZWZ5FQ.js.map +1 -0
- package/dist/{chunk-Y2HK44TG.js → chunk-D5KQ5OY6.js} +3 -3
- package/dist/{chunk-Y2HK44TG.js.map → chunk-D5KQ5OY6.js.map} +1 -1
- package/dist/{chunk-VHFQKAUL.js → chunk-FJG4PHTL.js} +83 -75
- package/dist/chunk-FJG4PHTL.js.map +1 -0
- package/dist/{chunk-LN6JDUGB.js → chunk-HXXTULDN.js} +2 -2
- package/dist/{chunk-LN6JDUGB.js.map → chunk-HXXTULDN.js.map} +1 -1
- package/dist/{chunk-L5WBGUVR.js → chunk-ISSVF5PT.js} +2753 -2654
- package/dist/chunk-ISSVF5PT.js.map +1 -0
- package/dist/chunk-NSOVI3AZ.js +170 -0
- package/dist/chunk-NSOVI3AZ.js.map +1 -0
- package/dist/{chunk-YQGQUBKA.js → chunk-TN7YSJVU.js} +62 -60
- package/dist/chunk-TN7YSJVU.js.map +1 -0
- package/dist/{chunk-4AMN4MMB.js → chunk-UDXOYZEC.js} +53 -39
- package/dist/chunk-UDXOYZEC.js.map +1 -0
- package/dist/{chunk-LJSIUFYD.js → chunk-ULDW42CR.js} +23 -2
- package/dist/chunk-ULDW42CR.js.map +1 -0
- package/dist/{chunk-QR5V3AFG.js → chunk-UTOEDPNU.js} +5 -5
- package/dist/{chunk-QR5V3AFG.js.map → chunk-UTOEDPNU.js.map} +1 -1
- package/dist/{chunk-UD7TEHZT.js → chunk-W2FJR5FF.js} +35 -22
- package/dist/chunk-W2FJR5FF.js.map +1 -0
- package/dist/{chunk-B5VWJBWM.js → chunk-WS6ZRV75.js} +3 -3
- package/dist/{chunk-B5VWJBWM.js.map → chunk-WS6ZRV75.js.map} +1 -1
- package/dist/{chunk-W3KSUXXR.js → chunk-XKENZTNE.js} +45 -14
- package/dist/chunk-XKENZTNE.js.map +1 -0
- package/dist/controls/index.d.ts +4 -3
- package/dist/controls/index.js +3 -3
- package/dist/dragdrop/index.d.ts +8 -8
- package/dist/dragdrop/index.js +2 -2
- package/dist/index.d.ts +75 -110
- package/dist/index.js +148 -115
- package/dist/index.js.map +1 -1
- package/dist/job/index.js +1 -1
- package/dist/layers/index.d.ts +26 -11
- package/dist/layers/index.js +3 -3
- package/dist/loupe/index.d.ts +7 -13
- package/dist/loupe/index.js +2 -2
- package/dist/passthrough/weasel-canvas.d.ts +3 -343
- package/dist/passthrough/weasel-canvas.js +1 -1
- package/dist/passthrough/weasel-ui.d.ts +123 -3088
- package/dist/passthrough/weasel-ui.js +2 -2
- package/dist/primitives/index.js +4 -4
- package/dist/state/index.d.ts +3 -3
- package/dist/state/index.js +2 -2
- package/dist/styles.css +30 -3
- package/dist/surface/index.js +2 -2
- package/dist/ui/layers/index.d.ts +22 -9
- package/dist/ui/layers/index.js +2 -2
- package/dist/undo/index.d.ts +6 -5
- package/package.json +8 -8
- package/src/annotations/AnnotationTargets.tsx +6 -1
- package/src/annotations/Annotations.overlay.test.tsx +2 -0
- package/src/annotations/types.ts +4 -1
- package/src/canvas/CanvasStack.tsx +8 -13
- package/src/canvas/useOrbit.test.ts +97 -1
- package/src/canvas/useOrbit.ts +41 -34
- package/src/canvas/usePanZoom.test.ts +106 -1
- package/src/canvas/usePanZoom.ts +54 -36
- package/src/chrome/ChromeRegions.stories.tsx +42 -1
- package/src/chrome/builtins.test.ts +4 -0
- package/src/chrome/builtins.tsx +18 -0
- package/src/chrome/index.ts +1 -1
- package/src/chrome/regions/SidebarRegion.tsx +7 -6
- package/src/chrome/regions/TitleBarRegion.test.tsx +64 -0
- package/src/chrome/regions/TitleBarRegion.tsx +16 -7
- package/src/chrome/regions/ToolbarRegion.test.tsx +14 -0
- package/src/chrome/regions/ToolbarRegion.tsx +2 -2
- package/src/chrome/regions/ViewportRegion.tsx +2 -2
- package/src/chrome/regions/regions.test.tsx +45 -1
- package/src/chrome/types.ts +21 -3
- package/src/controls/ControlPanel.test.tsx +38 -0
- package/src/controls/ControlPanel.tsx +51 -6
- package/src/dragdrop/DragDropRuntime.tsx +74 -61
- package/src/dragdrop/Palette.tsx +4 -3
- package/src/dragdrop/dragDrop.test.tsx +35 -12
- package/src/index.ts +2 -1
- package/src/instrument/types.ts +4 -5
- package/src/job/useJob.ts +1 -1
- package/src/lab/Lab.test.tsx +7 -0
- package/src/lab/Lab.tsx +2 -2
- package/src/lab/LabContext.ts +5 -1
- package/src/lab/LabShell.less +17 -2
- package/src/lab/Workspace.tsx +1 -1
- package/src/layers/AGENTS.md +29 -7
- package/src/layers/LayerList.less +16 -0
- package/src/layers/LayerList.stories.tsx +66 -0
- package/src/layers/LayerList.test.tsx +185 -2
- package/src/layers/LayerList.tsx +221 -74
- package/src/layers/index.ts +1 -1
- package/src/passthrough/weasel-ui.ts +5 -0
- package/src/primitives/FloatingPanel.test.tsx +87 -0
- package/src/primitives/FloatingPanel.tsx +59 -41
- package/src/state/store.test.ts +78 -0
- package/src/state/store.ts +27 -0
- package/src/state/types.ts +20 -0
- package/src/trial/Trial.less +4 -0
- package/src/trial/Trial.targets.test.tsx +96 -0
- package/src/trial/Trial.test.tsx +171 -14
- package/src/trial/Trial.tsx +4 -1
- package/src/trial/TrialChrome.tsx +22 -2
- package/src/trial/TrialTitleBar.tsx +7 -3
- package/src/trial/index.ts +1 -0
- package/src/trial/trialOps.test.ts +49 -1
- package/src/trial/trialOps.ts +28 -6
- package/dist/_dts/DrawCommand-B3bskUsC.d.ts +0 -564
- package/dist/_dts/PrefsForm-BkUJZx0A.d.ts +0 -204
- package/dist/_dts/fitViewToBounds-dZ2UDB6e.d.ts +0 -21
- package/dist/_dts/shapeKinds-Cx_rxwsa.d.ts +0 -87
- package/dist/_dts/types-C-gh9Ap-.d.ts +0 -695
- package/dist/chunk-4AMN4MMB.js.map +0 -1
- package/dist/chunk-7VW3S44V.js.map +0 -1
- package/dist/chunk-L5WBGUVR.js.map +0 -1
- package/dist/chunk-LJSIUFYD.js.map +0 -1
- package/dist/chunk-UD7TEHZT.js.map +0 -1
- package/dist/chunk-VHFQKAUL.js.map +0 -1
- package/dist/chunk-W3KSUXXR.js.map +0 -1
- package/dist/chunk-XCBCZEBO.js +0 -94
- package/dist/chunk-XCBCZEBO.js.map +0 -1
- package/dist/chunk-YQGQUBKA.js.map +0 -1
|
@@ -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-TORKRNFY.js
|
|
7
7
|
|
|
8
8
|
// ../gestures/dist/index.js
|
|
9
9
|
var GESTURE_DESCRIPTORS = [
|
|
@@ -287,7 +287,7 @@ function matchSpec(e, spec, isMac, phaseCtx) {
|
|
|
287
287
|
}
|
|
288
288
|
var EMPTY_ENGAGED = /* @__PURE__ */ new Set();
|
|
289
289
|
|
|
290
|
-
// ../core/dist/chunk-
|
|
290
|
+
// ../core/dist/chunk-TORKRNFY.js
|
|
291
291
|
var DepRegistryContext = createContext(null);
|
|
292
292
|
function DepRegistryProvider({ children }) {
|
|
293
293
|
const sourcesRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -437,6 +437,7 @@ function warnSharedScope() {
|
|
|
437
437
|
var ActionsContext = createContext(null);
|
|
438
438
|
function ActionsProvider({ children }) {
|
|
439
439
|
const actionsRef = useRef(/* @__PURE__ */ new Map());
|
|
440
|
+
const liveAction = (id) => actionsRef.current.get(id)?.at(-1);
|
|
440
441
|
const versionRef = useRef(0);
|
|
441
442
|
const cachedRef = useRef([]);
|
|
442
443
|
const cachedVerRef = useRef(-1);
|
|
@@ -451,7 +452,9 @@ function ActionsProvider({ children }) {
|
|
|
451
452
|
const snapshot = () => {
|
|
452
453
|
const v = versionRef.current;
|
|
453
454
|
if (cachedVerRef.current === v) return cachedRef.current;
|
|
454
|
-
const out = Object.freeze(
|
|
455
|
+
const out = Object.freeze(
|
|
456
|
+
Array.from(actionsRef.current.values(), (stack) => stack[stack.length - 1])
|
|
457
|
+
);
|
|
455
458
|
cachedRef.current = out;
|
|
456
459
|
cachedVerRef.current = v;
|
|
457
460
|
return out;
|
|
@@ -469,16 +472,23 @@ function ActionsProvider({ children }) {
|
|
|
469
472
|
register: (action) => {
|
|
470
473
|
validateActionId(action.id);
|
|
471
474
|
validateActionDefaultBinding(action);
|
|
472
|
-
actionsRef.current.
|
|
475
|
+
const stack = actionsRef.current.get(action.id);
|
|
476
|
+
if (stack) stack.push(action);
|
|
477
|
+
else actionsRef.current.set(action.id, [action]);
|
|
473
478
|
versionRef.current++;
|
|
474
479
|
notify2();
|
|
480
|
+
let released = false;
|
|
475
481
|
return () => {
|
|
482
|
+
if (released) return;
|
|
483
|
+
released = true;
|
|
476
484
|
const cur = actionsRef.current.get(action.id);
|
|
477
|
-
if (cur
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
485
|
+
if (!cur) return;
|
|
486
|
+
const i = cur.lastIndexOf(action);
|
|
487
|
+
if (i === -1) return;
|
|
488
|
+
cur.splice(i, 1);
|
|
489
|
+
if (cur.length === 0) actionsRef.current.delete(action.id);
|
|
490
|
+
versionRef.current++;
|
|
491
|
+
notify2();
|
|
482
492
|
};
|
|
483
493
|
},
|
|
484
494
|
unregister: (id) => {
|
|
@@ -489,7 +499,7 @@ function ActionsProvider({ children }) {
|
|
|
489
499
|
},
|
|
490
500
|
list: () => snapshot(),
|
|
491
501
|
trigger: (id, params) => {
|
|
492
|
-
const a =
|
|
502
|
+
const a = liveAction(id);
|
|
493
503
|
if (!a) return false;
|
|
494
504
|
try {
|
|
495
505
|
if (a.invoker && a.invoker.timing === "immediate") {
|
|
@@ -536,7 +546,7 @@ function ActionsProvider({ children }) {
|
|
|
536
546
|
const disp = dispatcherRef.current;
|
|
537
547
|
if (!disp) return null;
|
|
538
548
|
const r = wiredDepRegRef.current ?? depRegRef.current;
|
|
539
|
-
const a =
|
|
549
|
+
const a = liveAction(id);
|
|
540
550
|
const deps = !r ? {} : a?.requires ? buildDepsFromRequires(a, r) : {
|
|
541
551
|
selection: r.get("selection"),
|
|
542
552
|
scene: r.get("scene"),
|
|
@@ -2968,7 +2978,7 @@ var TEXT_SDF_UNIFORMS = [
|
|
|
2968
2978
|
];
|
|
2969
2979
|
var TEXT_SDF_ATTRIBUTES = ["a_position", "a_uv", "a_baselineY"];
|
|
2970
2980
|
|
|
2971
|
-
// ../text/dist/chunk-
|
|
2981
|
+
// ../text/dist/chunk-7ZHZKQEH.js
|
|
2972
2982
|
function resolveAlign(align, direction) {
|
|
2973
2983
|
if (align === "start") return direction === "rtl" ? "right" : "left";
|
|
2974
2984
|
if (align === "end") return direction === "rtl" ? "left" : "right";
|
|
@@ -3538,7 +3548,7 @@ function layoutRuns(runs, opts) {
|
|
|
3538
3548
|
cells[pos] = cell;
|
|
3539
3549
|
const step = e.advance + e.tracking;
|
|
3540
3550
|
const scale2 = e.fontSize / e.metrics.size;
|
|
3541
|
-
const baselineY = lineBaselineY - e.run.baselineShift;
|
|
3551
|
+
const baselineY = lineBaselineY - (e.run.baselineShift ?? 0);
|
|
3542
3552
|
if (e.run.underline || e.run.strikethrough || e.run.overline) {
|
|
3543
3553
|
if (span !== null && span.underline === e.run.underline && span.strikethrough === e.run.strikethrough && span.overline === e.run.overline && span.fontSize === e.fontSize && span.baselineY === baselineY && sameFill(span.fill, e.run.fill)) {
|
|
3544
3554
|
span.x1 = penX + step;
|
|
@@ -4660,7 +4670,7 @@ function serialToEntry(se, custom, logger) {
|
|
|
4660
4670
|
};
|
|
4661
4671
|
}
|
|
4662
4672
|
|
|
4663
|
-
// ../core/dist/chunk-
|
|
4673
|
+
// ../core/dist/chunk-KIVJXUYE.js
|
|
4664
4674
|
function worldToScreen(worldX, worldY, view) {
|
|
4665
4675
|
return [view.panX + worldX * view.zoom.x, view.panY + worldY * view.zoom.y];
|
|
4666
4676
|
}
|
|
@@ -4833,6 +4843,44 @@ void main() {
|
|
|
4833
4843
|
}
|
|
4834
4844
|
`
|
|
4835
4845
|
);
|
|
4846
|
+
var IMAGE_VOPACITY_VERT_SRC = (
|
|
4847
|
+
/* glsl */
|
|
4848
|
+
`#version 300 es
|
|
4849
|
+
in vec2 a_position;
|
|
4850
|
+
in vec2 a_uv;
|
|
4851
|
+
in float a_opacity;
|
|
4852
|
+
uniform mat3 u_proj;
|
|
4853
|
+
uniform mat3 u_model;
|
|
4854
|
+
out vec2 v_uv;
|
|
4855
|
+
out float v_opacity;
|
|
4856
|
+
void main() {
|
|
4857
|
+
vec3 screen = u_model * vec3(a_position, 1.0);
|
|
4858
|
+
vec3 clip = u_proj * vec3(screen.xy, 1.0);
|
|
4859
|
+
gl_Position = vec4(clip.xy, 0.0, 1.0);
|
|
4860
|
+
v_uv = a_uv;
|
|
4861
|
+
v_opacity = a_opacity;
|
|
4862
|
+
}
|
|
4863
|
+
`
|
|
4864
|
+
);
|
|
4865
|
+
var IMAGE_VOPACITY_FRAG_SRC = (
|
|
4866
|
+
/* glsl */
|
|
4867
|
+
`#version 300 es
|
|
4868
|
+
precision highp float;
|
|
4869
|
+
in vec2 v_uv;
|
|
4870
|
+
in float v_opacity;
|
|
4871
|
+
uniform sampler2D u_sampler;
|
|
4872
|
+
uniform float u_alpha;
|
|
4873
|
+
uniform mat4 u_colorMatrix;
|
|
4874
|
+
uniform vec4 u_colorBias;
|
|
4875
|
+
out vec4 outColor;
|
|
4876
|
+
void main() {
|
|
4877
|
+
vec4 texel = texture(u_sampler, v_uv);
|
|
4878
|
+
vec4 mapped = clamp(u_colorMatrix * texel + u_colorBias, 0.0, 1.0);
|
|
4879
|
+
float a = mapped.a * v_opacity * u_alpha;
|
|
4880
|
+
outColor = vec4(mapped.rgb * a, a);
|
|
4881
|
+
}
|
|
4882
|
+
`
|
|
4883
|
+
);
|
|
4836
4884
|
var IMAGE_FILL_UNIFORMS = [
|
|
4837
4885
|
"u_proj",
|
|
4838
4886
|
"u_model",
|
|
@@ -4843,6 +4891,15 @@ var IMAGE_FILL_UNIFORMS = [
|
|
|
4843
4891
|
"u_colorBias"
|
|
4844
4892
|
];
|
|
4845
4893
|
var IMAGE_FILL_ATTRIBUTES = ["a_position", "a_uv"];
|
|
4894
|
+
var IMAGE_VOPACITY_UNIFORMS = [
|
|
4895
|
+
"u_proj",
|
|
4896
|
+
"u_model",
|
|
4897
|
+
"u_sampler",
|
|
4898
|
+
"u_alpha",
|
|
4899
|
+
"u_colorMatrix",
|
|
4900
|
+
"u_colorBias"
|
|
4901
|
+
];
|
|
4902
|
+
var IMAGE_VOPACITY_ATTRIBUTES = ["a_position", "a_uv", "a_opacity"];
|
|
4846
4903
|
var GRAD_VERT_SRC = (
|
|
4847
4904
|
/* glsl */
|
|
4848
4905
|
`#version 300 es
|
|
@@ -5963,6 +6020,7 @@ seedBuiltins();
|
|
|
5963
6020
|
function getPaintKind(kind) {
|
|
5964
6021
|
return KINDS.get(kind ?? "solid");
|
|
5965
6022
|
}
|
|
6023
|
+
var SPRITE_STRIDE = 9;
|
|
5966
6024
|
function tessellate(path, opts = {}) {
|
|
5967
6025
|
if (path.kind === "rect") return tessellateRect(path);
|
|
5968
6026
|
return tessellatePolygon(path, opts);
|
|
@@ -7645,6 +7703,208 @@ var SolidBatch = class {
|
|
|
7645
7703
|
gl.deleteVertexArray(set.vao);
|
|
7646
7704
|
}
|
|
7647
7705
|
};
|
|
7706
|
+
var MAX_IMAGE_VERTICES_PER_BATCH = 32768;
|
|
7707
|
+
var FLOATS_PER_VERTEX2 = 5;
|
|
7708
|
+
var INITIAL_QUADS = 64;
|
|
7709
|
+
var TIERS = [
|
|
7710
|
+
{ quads: 1, slots: 64 },
|
|
7711
|
+
{ quads: 16, slots: 64 },
|
|
7712
|
+
{ quads: 256, slots: 16 }
|
|
7713
|
+
];
|
|
7714
|
+
TIERS[0].slots;
|
|
7715
|
+
var IMAGE_LARGE_RING_SIZE = 4;
|
|
7716
|
+
function doubledTo2(from, need) {
|
|
7717
|
+
let capacity = from;
|
|
7718
|
+
while (capacity < need) capacity *= 2;
|
|
7719
|
+
return capacity;
|
|
7720
|
+
}
|
|
7721
|
+
function quadIndices(quads) {
|
|
7722
|
+
const out = new Uint32Array(quads * 6);
|
|
7723
|
+
for (let q = 0; q < quads; q++) {
|
|
7724
|
+
const b = q * 4;
|
|
7725
|
+
const j = q * 6;
|
|
7726
|
+
out[j] = b;
|
|
7727
|
+
out[j + 1] = b + 1;
|
|
7728
|
+
out[j + 2] = b + 2;
|
|
7729
|
+
out[j + 3] = b;
|
|
7730
|
+
out[j + 4] = b + 2;
|
|
7731
|
+
out[j + 5] = b + 3;
|
|
7732
|
+
}
|
|
7733
|
+
return out;
|
|
7734
|
+
}
|
|
7735
|
+
var ImageBatch = class {
|
|
7736
|
+
gl;
|
|
7737
|
+
aPos;
|
|
7738
|
+
aUv;
|
|
7739
|
+
aOpacity;
|
|
7740
|
+
/** One ring per tier, cycled per flush. Slots are created on first use, so a
|
|
7741
|
+
* renderer that flushes rarely allocates as few as it flushes. */
|
|
7742
|
+
rings = TIERS.map((t) => new Array(t.slots).fill(void 0));
|
|
7743
|
+
nextInRing = TIERS.map(() => 0);
|
|
7744
|
+
/** For flushes past the largest tier; these sets grow to fit. */
|
|
7745
|
+
largeRing = new Array(IMAGE_LARGE_RING_SIZE).fill(void 0);
|
|
7746
|
+
nextLarge = 0;
|
|
7747
|
+
verts = new Float32Array(INITIAL_QUADS * 4 * FLOATS_PER_VERTEX2);
|
|
7748
|
+
nQuads = 0;
|
|
7749
|
+
constructor(gl, prog) {
|
|
7750
|
+
const aPos = prog.attribute("a_position");
|
|
7751
|
+
const aUv = prog.attribute("a_uv");
|
|
7752
|
+
const aOpacity = prog.attribute("a_opacity");
|
|
7753
|
+
if (aPos === void 0 || aUv === void 0 || aOpacity === void 0) {
|
|
7754
|
+
throw new Error(
|
|
7755
|
+
"ImageBatch: vertex-opacity program is missing a_position / a_uv / a_opacity"
|
|
7756
|
+
);
|
|
7757
|
+
}
|
|
7758
|
+
this.gl = gl;
|
|
7759
|
+
this.aPos = aPos;
|
|
7760
|
+
this.aUv = aUv;
|
|
7761
|
+
this.aOpacity = aOpacity;
|
|
7762
|
+
}
|
|
7763
|
+
/** Indices staged — what a caller passes to `drawElements`. */
|
|
7764
|
+
get length() {
|
|
7765
|
+
return this.nQuads * 6;
|
|
7766
|
+
}
|
|
7767
|
+
get quads() {
|
|
7768
|
+
return this.nQuads;
|
|
7769
|
+
}
|
|
7770
|
+
/** Whether staging one more quad would put the run past the per-flush cap. */
|
|
7771
|
+
wouldOverflow() {
|
|
7772
|
+
return (this.nQuads + 1) * 4 > MAX_IMAGE_VERTICES_PER_BATCH;
|
|
7773
|
+
}
|
|
7774
|
+
/**
|
|
7775
|
+
* Append one image quad: the destination rect `(x, y, w, h)` mapped through
|
|
7776
|
+
* `m`, sampling `(u0, v0)`-`(u1, v1)`, every corner carrying `opacity`.
|
|
7777
|
+
*
|
|
7778
|
+
* An affine maps a rect to a parallelogram, so two triangles still cover it
|
|
7779
|
+
* and the batch draws at `u_model` identity. Corners wind top-left,
|
|
7780
|
+
* top-right, bottom-right, bottom-left, with UVs following — the flips a
|
|
7781
|
+
* command asks for are already in the `u`/`v` the caller passes.
|
|
7782
|
+
*/
|
|
7783
|
+
pushQuad(x, y, w, h, m, u0, v0, u1, v1, opacity) {
|
|
7784
|
+
this.reserve();
|
|
7785
|
+
const v = this.verts;
|
|
7786
|
+
let i = this.nQuads * 4 * FLOATS_PER_VERTEX2;
|
|
7787
|
+
const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];
|
|
7788
|
+
const x1 = x + w;
|
|
7789
|
+
const y1 = y + h;
|
|
7790
|
+
const ax = ma * x + mc * y + mtx, ay = mb * x + md * y + mty;
|
|
7791
|
+
const bx = ma * x1 + mc * y + mtx, by = mb * x1 + md * y + mty;
|
|
7792
|
+
const cx = ma * x1 + mc * y1 + mtx, cy = mb * x1 + md * y1 + mty;
|
|
7793
|
+
const dx = ma * x + mc * y1 + mtx, dy = mb * x + md * y1 + mty;
|
|
7794
|
+
v[i++] = ax;
|
|
7795
|
+
v[i++] = ay;
|
|
7796
|
+
v[i++] = u0;
|
|
7797
|
+
v[i++] = v0;
|
|
7798
|
+
v[i++] = opacity;
|
|
7799
|
+
v[i++] = bx;
|
|
7800
|
+
v[i++] = by;
|
|
7801
|
+
v[i++] = u1;
|
|
7802
|
+
v[i++] = v0;
|
|
7803
|
+
v[i++] = opacity;
|
|
7804
|
+
v[i++] = cx;
|
|
7805
|
+
v[i++] = cy;
|
|
7806
|
+
v[i++] = u1;
|
|
7807
|
+
v[i++] = v1;
|
|
7808
|
+
v[i++] = opacity;
|
|
7809
|
+
v[i++] = dx;
|
|
7810
|
+
v[i++] = dy;
|
|
7811
|
+
v[i++] = u0;
|
|
7812
|
+
v[i++] = v1;
|
|
7813
|
+
v[i++] = opacity;
|
|
7814
|
+
this.nQuads += 1;
|
|
7815
|
+
}
|
|
7816
|
+
/** Upload the staged geometry into the next set of buffers and bind its VAO.
|
|
7817
|
+
* Returns the index count for the caller's `drawElements`. */
|
|
7818
|
+
uploadAndBind() {
|
|
7819
|
+
const gl = this.gl;
|
|
7820
|
+
const tier = TIERS.findIndex((t) => this.nQuads <= t.quads);
|
|
7821
|
+
const set = tier < 0 ? this.nextLargeSlot() : this.nextRingSlot(tier);
|
|
7822
|
+
gl.bindVertexArray(set.vao);
|
|
7823
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, set.vbo);
|
|
7824
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verts, 0, this.nQuads * 4 * FLOATS_PER_VERTEX2);
|
|
7825
|
+
return this.nQuads * 6;
|
|
7826
|
+
}
|
|
7827
|
+
reset() {
|
|
7828
|
+
this.nQuads = 0;
|
|
7829
|
+
}
|
|
7830
|
+
dispose() {
|
|
7831
|
+
for (const set of [...this.rings.flat(), ...this.largeRing]) {
|
|
7832
|
+
if (set) this.deleteSet(set);
|
|
7833
|
+
}
|
|
7834
|
+
for (const ring of this.rings) ring.fill(void 0);
|
|
7835
|
+
this.largeRing.fill(void 0);
|
|
7836
|
+
}
|
|
7837
|
+
/** Grow the CPU arrays so one more quad fits. */
|
|
7838
|
+
reserve() {
|
|
7839
|
+
const need = (this.nQuads + 1) * 4 * FLOATS_PER_VERTEX2;
|
|
7840
|
+
if (need <= this.verts.length) return;
|
|
7841
|
+
const grown = new Float32Array(doubledTo2(this.verts.length, need));
|
|
7842
|
+
grown.set(this.verts);
|
|
7843
|
+
this.verts = grown;
|
|
7844
|
+
}
|
|
7845
|
+
nextRingSlot(tier) {
|
|
7846
|
+
const ring = this.rings[tier];
|
|
7847
|
+
const slot = this.nextInRing[tier];
|
|
7848
|
+
this.nextInRing[tier] = (slot + 1) % ring.length;
|
|
7849
|
+
const existing = ring[slot];
|
|
7850
|
+
if (existing) return existing;
|
|
7851
|
+
const set = this.createSet(TIERS[tier].quads);
|
|
7852
|
+
ring[slot] = set;
|
|
7853
|
+
return set;
|
|
7854
|
+
}
|
|
7855
|
+
nextLargeSlot() {
|
|
7856
|
+
const gl = this.gl;
|
|
7857
|
+
const slot = this.nextLarge;
|
|
7858
|
+
this.nextLarge = (slot + 1) % IMAGE_LARGE_RING_SIZE;
|
|
7859
|
+
let set = this.largeRing[slot];
|
|
7860
|
+
if (!set) {
|
|
7861
|
+
set = this.createSet(doubledTo2(TIERS[TIERS.length - 1].quads, this.nQuads));
|
|
7862
|
+
this.largeRing[slot] = set;
|
|
7863
|
+
return set;
|
|
7864
|
+
}
|
|
7865
|
+
if (this.nQuads > set.quadCapacity) {
|
|
7866
|
+
set.quadCapacity = doubledTo2(set.quadCapacity, this.nQuads);
|
|
7867
|
+
gl.bindVertexArray(set.vao);
|
|
7868
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, set.vbo);
|
|
7869
|
+
gl.bufferData(
|
|
7870
|
+
gl.ARRAY_BUFFER,
|
|
7871
|
+
set.quadCapacity * 4 * FLOATS_PER_VERTEX2 * 4,
|
|
7872
|
+
gl.DYNAMIC_DRAW
|
|
7873
|
+
);
|
|
7874
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, set.ibo);
|
|
7875
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, quadIndices(set.quadCapacity), gl.STATIC_DRAW);
|
|
7876
|
+
gl.bindVertexArray(null);
|
|
7877
|
+
}
|
|
7878
|
+
return set;
|
|
7879
|
+
}
|
|
7880
|
+
createSet(quads) {
|
|
7881
|
+
const gl = this.gl;
|
|
7882
|
+
const vao = gl.createVertexArray();
|
|
7883
|
+
const vbo = gl.createBuffer();
|
|
7884
|
+
const ibo = gl.createBuffer();
|
|
7885
|
+
if (!vao || !vbo || !ibo) throw new Error("ImageBatch: failed to create GL objects");
|
|
7886
|
+
const stride = FLOATS_PER_VERTEX2 * 4;
|
|
7887
|
+
gl.bindVertexArray(vao);
|
|
7888
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
7889
|
+
gl.bufferData(gl.ARRAY_BUFFER, quads * 4 * stride, gl.DYNAMIC_DRAW);
|
|
7890
|
+
gl.enableVertexAttribArray(this.aPos);
|
|
7891
|
+
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, stride, 0);
|
|
7892
|
+
gl.enableVertexAttribArray(this.aUv);
|
|
7893
|
+
gl.vertexAttribPointer(this.aUv, 2, gl.FLOAT, false, stride, 8);
|
|
7894
|
+
gl.enableVertexAttribArray(this.aOpacity);
|
|
7895
|
+
gl.vertexAttribPointer(this.aOpacity, 1, gl.FLOAT, false, stride, 16);
|
|
7896
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
|
|
7897
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, quadIndices(quads), gl.STATIC_DRAW);
|
|
7898
|
+
gl.bindVertexArray(null);
|
|
7899
|
+
return { vao, vbo, ibo, quadCapacity: quads };
|
|
7900
|
+
}
|
|
7901
|
+
deleteSet(set) {
|
|
7902
|
+
const gl = this.gl;
|
|
7903
|
+
gl.deleteBuffer(set.vbo);
|
|
7904
|
+
gl.deleteBuffer(set.ibo);
|
|
7905
|
+
gl.deleteVertexArray(set.vao);
|
|
7906
|
+
}
|
|
7907
|
+
};
|
|
7648
7908
|
var FRAME_UPLOADS = /* @__PURE__ */ new WeakMap();
|
|
7649
7909
|
var FRAME_PROJ = /* @__PURE__ */ new WeakMap();
|
|
7650
7910
|
function uploadedFor(ctx, prog) {
|
|
@@ -7738,13 +7998,14 @@ function dispatch(ctx, cmd) {
|
|
|
7738
7998
|
case "path":
|
|
7739
7999
|
return drawPath(ctx, cmd);
|
|
7740
8000
|
case "text":
|
|
7741
|
-
|
|
8001
|
+
flushBatches(ctx);
|
|
7742
8002
|
return drawText(ctx, cmd);
|
|
7743
8003
|
case "image":
|
|
7744
|
-
flushSolids(ctx);
|
|
7745
8004
|
return drawImage(ctx, cmd);
|
|
8005
|
+
case "sprites":
|
|
8006
|
+
return drawSprites(ctx, cmd);
|
|
7746
8007
|
case "shader":
|
|
7747
|
-
|
|
8008
|
+
flushBatches(ctx);
|
|
7748
8009
|
return drawShader(ctx, cmd);
|
|
7749
8010
|
}
|
|
7750
8011
|
}
|
|
@@ -7921,6 +8182,7 @@ function canBatchMesh(mesh) {
|
|
|
7921
8182
|
return !mesh.requiresStencil && mesh.vertices.length >> 1 <= MAX_BATCHED_MESH_VERTICES;
|
|
7922
8183
|
}
|
|
7923
8184
|
function stageSolid(ctx, vertices) {
|
|
8185
|
+
flushImages(ctx);
|
|
7924
8186
|
if (ctx.solidState !== void 0 && !stagedStateIsLive(ctx, ctx.solidState)) flushSolids(ctx);
|
|
7925
8187
|
if (ctx.solidBatch.wouldOverflow(vertices)) flushSolids(ctx);
|
|
7926
8188
|
if (ctx.solidState === void 0) {
|
|
@@ -7964,7 +8226,7 @@ function tryStageSolid(ctx, mesh, paint) {
|
|
|
7964
8226
|
pushMesh(ctx, mesh, paint);
|
|
7965
8227
|
return true;
|
|
7966
8228
|
}
|
|
7967
|
-
|
|
8229
|
+
flushBatches(ctx);
|
|
7968
8230
|
return false;
|
|
7969
8231
|
}
|
|
7970
8232
|
function flushSolids(ctx) {
|
|
@@ -7985,6 +8247,56 @@ function flushSolids(ctx) {
|
|
|
7985
8247
|
batch.reset();
|
|
7986
8248
|
ctx.solidState = void 0;
|
|
7987
8249
|
}
|
|
8250
|
+
function stagedImageStateIsLive(ctx, staged, image, sampling) {
|
|
8251
|
+
if (staged.image !== image) return false;
|
|
8252
|
+
if (staged.sampling !== sampling) return false;
|
|
8253
|
+
if (staged.clipDepth !== ctx.clipDepth) return false;
|
|
8254
|
+
const colorMatrix = ctx.state.colorMatrix;
|
|
8255
|
+
return staged.colorMatrix === colorMatrix || sameValues(staged.colorMatrix, colorMatrix);
|
|
8256
|
+
}
|
|
8257
|
+
function stageImage(ctx, image, sampling) {
|
|
8258
|
+
flushSolids(ctx);
|
|
8259
|
+
if (ctx.imageState !== void 0 && !stagedImageStateIsLive(ctx, ctx.imageState, image, sampling)) {
|
|
8260
|
+
flushImages(ctx);
|
|
8261
|
+
}
|
|
8262
|
+
if (ctx.imageBatch.wouldOverflow()) flushImages(ctx);
|
|
8263
|
+
if (ctx.imageState === void 0) {
|
|
8264
|
+
ctx.imageState = {
|
|
8265
|
+
image,
|
|
8266
|
+
sampling,
|
|
8267
|
+
colorMatrix: ctx.state.colorMatrix,
|
|
8268
|
+
clipDepth: ctx.clipDepth
|
|
8269
|
+
};
|
|
8270
|
+
}
|
|
8271
|
+
}
|
|
8272
|
+
function flushImages(ctx) {
|
|
8273
|
+
const batch = ctx.imageBatch;
|
|
8274
|
+
const staged = ctx.imageState;
|
|
8275
|
+
if (batch.length === 0 || staged === void 0) return;
|
|
8276
|
+
const gl = ctx.gl;
|
|
8277
|
+
const prog = ctx.imageFillVOpacity;
|
|
8278
|
+
gl.useProgram(prog.handle);
|
|
8279
|
+
const indexCount = batch.uploadAndBind();
|
|
8280
|
+
setProjAndModel(ctx, prog, BATCH_MODEL);
|
|
8281
|
+
setAlphaUniform(ctx, prog, 1);
|
|
8282
|
+
setColorMatrixUniforms(ctx, prog, staged.colorMatrix);
|
|
8283
|
+
ctx.imageCache.bind(staged.image, 0);
|
|
8284
|
+
gl.texParameteri(
|
|
8285
|
+
gl.TEXTURE_2D,
|
|
8286
|
+
gl.TEXTURE_MAG_FILTER,
|
|
8287
|
+
staged.sampling === "nearest" ? gl.NEAREST : gl.LINEAR
|
|
8288
|
+
);
|
|
8289
|
+
gl.uniform1i(prog.uniform("u_sampler"), 0);
|
|
8290
|
+
applyClipTest(ctx, staged.clipDepth);
|
|
8291
|
+
gl.drawElements(gl.TRIANGLES, indexCount, gl.UNSIGNED_INT, 0);
|
|
8292
|
+
gl.bindVertexArray(null);
|
|
8293
|
+
batch.reset();
|
|
8294
|
+
ctx.imageState = void 0;
|
|
8295
|
+
}
|
|
8296
|
+
function flushBatches(ctx) {
|
|
8297
|
+
flushSolids(ctx);
|
|
8298
|
+
flushImages(ctx);
|
|
8299
|
+
}
|
|
7988
8300
|
function expandAnchorColors(perAnchor, handle) {
|
|
7989
8301
|
const aA = handle.anchorA;
|
|
7990
8302
|
const aB = handle.anchorB;
|
|
@@ -8188,7 +8500,7 @@ function rasterizePathToStencil(ctx, path) {
|
|
|
8188
8500
|
gl.bindVertexArray(null);
|
|
8189
8501
|
}
|
|
8190
8502
|
function pushClip(ctx, path, newDepth) {
|
|
8191
|
-
|
|
8503
|
+
flushBatches(ctx);
|
|
8192
8504
|
const gl = ctx.gl;
|
|
8193
8505
|
const ancestors = ancestorMask(newDepth - 1);
|
|
8194
8506
|
const newBit = 1 << newDepth;
|
|
@@ -8203,7 +8515,7 @@ function pushClip(ctx, path, newDepth) {
|
|
|
8203
8515
|
gl.stencilMask(255);
|
|
8204
8516
|
}
|
|
8205
8517
|
function popClip(ctx, path, oldDepth) {
|
|
8206
|
-
|
|
8518
|
+
flushBatches(ctx);
|
|
8207
8519
|
const gl = ctx.gl;
|
|
8208
8520
|
gl.enable(gl.STENCIL_TEST);
|
|
8209
8521
|
const oldBit = 1 << oldDepth + 1;
|
|
@@ -8250,7 +8562,7 @@ function drawPathStroke(ctx, rawCmd) {
|
|
|
8250
8562
|
const stroke = cmd.stroke;
|
|
8251
8563
|
const align = stroke.align ?? "center";
|
|
8252
8564
|
if (cmd.path.kind === "polygon" && align !== "center") {
|
|
8253
|
-
|
|
8565
|
+
flushBatches(ctx);
|
|
8254
8566
|
drawPathStrokeStenciled(ctx, cmd, align);
|
|
8255
8567
|
return;
|
|
8256
8568
|
}
|
|
@@ -8598,45 +8910,6 @@ function drawTextGroup(ctx, group, prog, dx, dy) {
|
|
|
8598
8910
|
gl.drawElements(gl.TRIANGLES, group.quads.length * 6, gl.UNSIGNED_INT, 0);
|
|
8599
8911
|
gl.bindVertexArray(null);
|
|
8600
8912
|
}
|
|
8601
|
-
var IMAGE_QUAD_RING_SIZE = 64;
|
|
8602
|
-
var IMAGE_QUAD_RINGS = /* @__PURE__ */ new WeakMap();
|
|
8603
|
-
var IMAGE_QUAD_INDICES = new Uint32Array([0, 1, 2, 1, 3, 2]);
|
|
8604
|
-
var IMAGE_QUAD_STRIDE = 16;
|
|
8605
|
-
function imageQuadRing(gl, prog) {
|
|
8606
|
-
const existing = IMAGE_QUAD_RINGS.get(prog);
|
|
8607
|
-
if (existing) return existing;
|
|
8608
|
-
const aPosLoc = prog.attribute("a_position");
|
|
8609
|
-
const aUvLoc = prog.attribute("a_uv");
|
|
8610
|
-
const ibo = gl.createBuffer();
|
|
8611
|
-
if (!ibo) throw new Error("drawImage: createBuffer (IBO) returned null");
|
|
8612
|
-
const vaos = [];
|
|
8613
|
-
const vbos = [];
|
|
8614
|
-
for (let slot = 0; slot < IMAGE_QUAD_RING_SIZE; slot++) {
|
|
8615
|
-
const vao = gl.createVertexArray();
|
|
8616
|
-
const vbo = gl.createBuffer();
|
|
8617
|
-
if (!vao) throw new Error("drawImage: createVertexArray returned null");
|
|
8618
|
-
if (!vbo) throw new Error("drawImage: createBuffer returned null");
|
|
8619
|
-
gl.bindVertexArray(vao);
|
|
8620
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
8621
|
-
gl.bufferData(gl.ARRAY_BUFFER, 4 * IMAGE_QUAD_STRIDE, gl.DYNAMIC_DRAW);
|
|
8622
|
-
if (aPosLoc !== void 0) {
|
|
8623
|
-
gl.enableVertexAttribArray(aPosLoc);
|
|
8624
|
-
gl.vertexAttribPointer(aPosLoc, 2, gl.FLOAT, false, IMAGE_QUAD_STRIDE, 0);
|
|
8625
|
-
}
|
|
8626
|
-
if (aUvLoc !== void 0) {
|
|
8627
|
-
gl.enableVertexAttribArray(aUvLoc);
|
|
8628
|
-
gl.vertexAttribPointer(aUvLoc, 2, gl.FLOAT, false, IMAGE_QUAD_STRIDE, 8);
|
|
8629
|
-
}
|
|
8630
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
|
|
8631
|
-
if (slot === 0) gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, IMAGE_QUAD_INDICES, gl.STATIC_DRAW);
|
|
8632
|
-
gl.bindVertexArray(null);
|
|
8633
|
-
vaos.push(vao);
|
|
8634
|
-
vbos.push(vbo);
|
|
8635
|
-
}
|
|
8636
|
-
const ring = { vaos, vbos, ibo, next: 0 };
|
|
8637
|
-
IMAGE_QUAD_RINGS.set(prog, ring);
|
|
8638
|
-
return ring;
|
|
8639
|
-
}
|
|
8640
8913
|
var TEXT_QUAD_RING_SIZE = 64;
|
|
8641
8914
|
var TEXT_QUAD_RINGS = /* @__PURE__ */ new WeakMap();
|
|
8642
8915
|
function grownTo(need) {
|
|
@@ -8714,22 +8987,9 @@ function disposeTextQuads(gl, prog) {
|
|
|
8714
8987
|
gl.deleteBuffer(ring.ibo);
|
|
8715
8988
|
TEXT_QUAD_RINGS.delete(prog);
|
|
8716
8989
|
}
|
|
8717
|
-
function disposeImageQuads(gl, prog) {
|
|
8718
|
-
const ring = IMAGE_QUAD_RINGS.get(prog);
|
|
8719
|
-
if (!ring) return;
|
|
8720
|
-
for (const vao of ring.vaos) gl.deleteVertexArray(vao);
|
|
8721
|
-
for (const vbo of ring.vbos) gl.deleteBuffer(vbo);
|
|
8722
|
-
gl.deleteBuffer(ring.ibo);
|
|
8723
|
-
IMAGE_QUAD_RINGS.delete(prog);
|
|
8724
|
-
}
|
|
8725
|
-
var IMAGE_QUAD_VERTICES = new Float32Array(16);
|
|
8726
8990
|
function drawImage(ctx, cmd) {
|
|
8727
8991
|
ctx.imageCache.upload(cmd.image, cmd.image);
|
|
8728
|
-
|
|
8729
|
-
const prog = ctx.imageFill;
|
|
8730
|
-
gl.useProgram(prog.handle);
|
|
8731
|
-
const x0 = cmd.x, y0 = cmd.y;
|
|
8732
|
-
const x1 = cmd.x + cmd.w, y1 = cmd.y + cmd.h;
|
|
8992
|
+
stageImage(ctx, cmd.image, cmd.sampling ?? "linear");
|
|
8733
8993
|
const src = cmd.source;
|
|
8734
8994
|
let u0 = 0, v0 = 0, u1 = 1, v1 = 1;
|
|
8735
8995
|
if (src) {
|
|
@@ -8749,43 +9009,50 @@ function drawImage(ctx, cmd) {
|
|
|
8749
9009
|
v0 = v1;
|
|
8750
9010
|
v1 = t;
|
|
8751
9011
|
}
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
v[10] = u0;
|
|
8764
|
-
v[11] = v1;
|
|
8765
|
-
v[12] = x1;
|
|
8766
|
-
v[13] = y1;
|
|
8767
|
-
v[14] = u1;
|
|
8768
|
-
v[15] = v1;
|
|
8769
|
-
const ring = imageQuadRing(gl, prog);
|
|
8770
|
-
const slot = ring.next;
|
|
8771
|
-
ring.next = (slot + 1) % IMAGE_QUAD_RING_SIZE;
|
|
8772
|
-
gl.bindVertexArray(ring.vaos[slot]);
|
|
8773
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, ring.vbos[slot]);
|
|
8774
|
-
gl.bufferSubData(gl.ARRAY_BUFFER, 0, v);
|
|
8775
|
-
setProjAndModel(ctx, prog);
|
|
8776
|
-
setColorMatrixUniforms(ctx, prog);
|
|
8777
|
-
ctx.imageCache.bind(cmd.image, 0);
|
|
8778
|
-
gl.texParameteri(
|
|
8779
|
-
gl.TEXTURE_2D,
|
|
8780
|
-
gl.TEXTURE_MAG_FILTER,
|
|
8781
|
-
cmd.sampling === "nearest" ? gl.NEAREST : gl.LINEAR
|
|
9012
|
+
ctx.imageBatch.pushQuad(
|
|
9013
|
+
cmd.x,
|
|
9014
|
+
cmd.y,
|
|
9015
|
+
cmd.w,
|
|
9016
|
+
cmd.h,
|
|
9017
|
+
ctx.state.transform,
|
|
9018
|
+
u0,
|
|
9019
|
+
v0,
|
|
9020
|
+
u1,
|
|
9021
|
+
v1,
|
|
9022
|
+
(cmd.opacity ?? 1) * ctx.state.alpha
|
|
8782
9023
|
);
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
|
|
9024
|
+
}
|
|
9025
|
+
function drawSprites(ctx, cmd) {
|
|
9026
|
+
const data = cmd.sprites;
|
|
9027
|
+
const count = Math.floor(data.length / SPRITE_STRIDE);
|
|
9028
|
+
if (count === 0) return;
|
|
9029
|
+
ctx.imageCache.upload(cmd.image, cmd.image);
|
|
9030
|
+
const sampling = cmd.sampling ?? "linear";
|
|
9031
|
+
stageImage(ctx, cmd.image, sampling);
|
|
9032
|
+
const batch = ctx.imageBatch;
|
|
9033
|
+
const m = ctx.state.transform;
|
|
9034
|
+
const groupAlpha = ctx.state.alpha;
|
|
9035
|
+
const tw = cmd.image.width;
|
|
9036
|
+
const th = cmd.image.height;
|
|
9037
|
+
for (let s = 0, i = 0; s < count; s++, i += SPRITE_STRIDE) {
|
|
9038
|
+
if (batch.wouldOverflow()) {
|
|
9039
|
+
flushImages(ctx);
|
|
9040
|
+
stageImage(ctx, cmd.image, sampling);
|
|
9041
|
+
}
|
|
9042
|
+
const sx = data[i + 4], sy = data[i + 5], sw = data[i + 6], sh = data[i + 7];
|
|
9043
|
+
batch.pushQuad(
|
|
9044
|
+
data[i],
|
|
9045
|
+
data[i + 1],
|
|
9046
|
+
data[i + 2],
|
|
9047
|
+
data[i + 3],
|
|
9048
|
+
m,
|
|
9049
|
+
sx / tw,
|
|
9050
|
+
sy / th,
|
|
9051
|
+
(sx + sw) / tw,
|
|
9052
|
+
(sy + sh) / th,
|
|
9053
|
+
data[i + 8] * groupAlpha
|
|
9054
|
+
);
|
|
9055
|
+
}
|
|
8789
9056
|
}
|
|
8790
9057
|
var CUSTOM_VERT_SRC = (
|
|
8791
9058
|
/* glsl */
|
|
@@ -8874,6 +9141,7 @@ var WeaselRenderer = class {
|
|
|
8874
9141
|
textSdf;
|
|
8875
9142
|
textSdfR8;
|
|
8876
9143
|
imageFill;
|
|
9144
|
+
imageFillVOpacity;
|
|
8877
9145
|
gradFill;
|
|
8878
9146
|
patternFill;
|
|
8879
9147
|
meshCache;
|
|
@@ -8884,6 +9152,7 @@ var WeaselRenderer = class {
|
|
|
8884
9152
|
quadVbo = null;
|
|
8885
9153
|
quadIbo = null;
|
|
8886
9154
|
solidBatch;
|
|
9155
|
+
imageBatch;
|
|
8887
9156
|
groupState = new GroupState();
|
|
8888
9157
|
widthCss;
|
|
8889
9158
|
heightCss;
|
|
@@ -8948,6 +9217,13 @@ var WeaselRenderer = class {
|
|
|
8948
9217
|
this.imageFill = new ShaderProgram(this.gl, IMAGE_VERT_SRC, IMAGE_FRAG_SRC);
|
|
8949
9218
|
this.imageFill.lookupUniforms(IMAGE_FILL_UNIFORMS);
|
|
8950
9219
|
this.imageFill.lookupAttributes(IMAGE_FILL_ATTRIBUTES);
|
|
9220
|
+
this.imageFillVOpacity = new ShaderProgram(
|
|
9221
|
+
this.gl,
|
|
9222
|
+
IMAGE_VOPACITY_VERT_SRC,
|
|
9223
|
+
IMAGE_VOPACITY_FRAG_SRC
|
|
9224
|
+
);
|
|
9225
|
+
this.imageFillVOpacity.lookupUniforms(IMAGE_VOPACITY_UNIFORMS);
|
|
9226
|
+
this.imageFillVOpacity.lookupAttributes(IMAGE_VOPACITY_ATTRIBUTES);
|
|
8951
9227
|
this.gradFill = new ShaderProgram(this.gl, GRAD_VERT_SRC, GRAD_FRAG_SRC);
|
|
8952
9228
|
this.gradFill.lookupUniforms(GRAD_FILL_UNIFORMS);
|
|
8953
9229
|
this.gradFill.lookupAttributes(GRAD_FILL_ATTRIBUTES);
|
|
@@ -8962,6 +9238,7 @@ var WeaselRenderer = class {
|
|
|
8962
9238
|
this.gradRampCache = new GradientRampCache(this.gl);
|
|
8963
9239
|
this.uploadQuadGeometry();
|
|
8964
9240
|
this.solidBatch = new SolidBatch(this.gl, this.pathFillVColor);
|
|
9241
|
+
this.imageBatch = new ImageBatch(this.gl, this.imageFillVOpacity);
|
|
8965
9242
|
}
|
|
8966
9243
|
uploadQuadGeometry() {
|
|
8967
9244
|
const gl = this.gl;
|
|
@@ -9085,6 +9362,13 @@ var WeaselRenderer = class {
|
|
|
9085
9362
|
this.imageFill = new ShaderProgram(this.gl, IMAGE_VERT_SRC, IMAGE_FRAG_SRC);
|
|
9086
9363
|
this.imageFill.lookupUniforms(IMAGE_FILL_UNIFORMS);
|
|
9087
9364
|
this.imageFill.lookupAttributes(IMAGE_FILL_ATTRIBUTES);
|
|
9365
|
+
this.imageFillVOpacity = new ShaderProgram(
|
|
9366
|
+
this.gl,
|
|
9367
|
+
IMAGE_VOPACITY_VERT_SRC,
|
|
9368
|
+
IMAGE_VOPACITY_FRAG_SRC
|
|
9369
|
+
);
|
|
9370
|
+
this.imageFillVOpacity.lookupUniforms(IMAGE_VOPACITY_UNIFORMS);
|
|
9371
|
+
this.imageFillVOpacity.lookupAttributes(IMAGE_VOPACITY_ATTRIBUTES);
|
|
9088
9372
|
this.gradFill = new ShaderProgram(this.gl, GRAD_VERT_SRC, GRAD_FRAG_SRC);
|
|
9089
9373
|
this.gradFill.lookupUniforms(GRAD_FILL_UNIFORMS);
|
|
9090
9374
|
this.gradFill.lookupAttributes(GRAD_FILL_ATTRIBUTES);
|
|
@@ -9099,6 +9383,7 @@ var WeaselRenderer = class {
|
|
|
9099
9383
|
this.gradRampCache = new GradientRampCache(this.gl);
|
|
9100
9384
|
this.uploadQuadGeometry();
|
|
9101
9385
|
this.solidBatch = new SolidBatch(this.gl, this.pathFillVColor);
|
|
9386
|
+
this.imageBatch = new ImageBatch(this.gl, this.imageFillVOpacity);
|
|
9102
9387
|
for (const id of this.programRegistry.keys()) {
|
|
9103
9388
|
const src = getProgramSource(id);
|
|
9104
9389
|
if (!src) continue;
|
|
@@ -9147,7 +9432,7 @@ var WeaselRenderer = class {
|
|
|
9147
9432
|
}
|
|
9148
9433
|
this.meshCache.freeTransient();
|
|
9149
9434
|
this.meshCache.drainPendingDeletes();
|
|
9150
|
-
for (const prog of [this.pathFill, this.pathFillVColor, this.textSdf, this.textSdfR8, this.imageFill, this.gradFill, this.patternFill]) {
|
|
9435
|
+
for (const prog of [this.pathFill, this.pathFillVColor, this.textSdf, this.textSdfR8, this.imageFill, this.imageFillVOpacity, this.gradFill, this.patternFill]) {
|
|
9151
9436
|
gl.deleteProgram(prog.handle);
|
|
9152
9437
|
}
|
|
9153
9438
|
for (const prog of this.programRegistry.values()) {
|
|
@@ -9158,9 +9443,9 @@ var WeaselRenderer = class {
|
|
|
9158
9443
|
this.gradRampCache.free();
|
|
9159
9444
|
if (this.quadVbo) gl.deleteBuffer(this.quadVbo);
|
|
9160
9445
|
if (this.quadIbo) gl.deleteBuffer(this.quadIbo);
|
|
9161
|
-
disposeImageQuads(gl, this.imageFill);
|
|
9162
9446
|
for (const prog of [this.textSdf, this.textSdfR8, this.pathFill]) disposeTextQuads(gl, prog);
|
|
9163
9447
|
this.solidBatch.dispose();
|
|
9448
|
+
this.imageBatch.dispose();
|
|
9164
9449
|
}
|
|
9165
9450
|
/**
|
|
9166
9451
|
* Draw one frame.
|
|
@@ -9189,6 +9474,7 @@ var WeaselRenderer = class {
|
|
|
9189
9474
|
textSdf: this.textSdf,
|
|
9190
9475
|
textSdfR8: this.textSdfR8,
|
|
9191
9476
|
imageFill: this.imageFill,
|
|
9477
|
+
imageFillVOpacity: this.imageFillVOpacity,
|
|
9192
9478
|
gradFill: this.gradFill,
|
|
9193
9479
|
patternFill: this.patternFill,
|
|
9194
9480
|
meshCache: this.meshCache,
|
|
@@ -9200,6 +9486,7 @@ var WeaselRenderer = class {
|
|
|
9200
9486
|
quadVbo: this.quadVbo,
|
|
9201
9487
|
quadIbo: this.quadIbo,
|
|
9202
9488
|
solidBatch: this.solidBatch,
|
|
9489
|
+
imageBatch: this.imageBatch,
|
|
9203
9490
|
state: this.groupState,
|
|
9204
9491
|
widthCss: this.widthCss,
|
|
9205
9492
|
heightCss: this.heightCss,
|
|
@@ -9209,7 +9496,7 @@ var WeaselRenderer = class {
|
|
|
9209
9496
|
viewMatrix: viewMatrix2
|
|
9210
9497
|
};
|
|
9211
9498
|
for (const cmd of commands) dispatch(ctx, cmd);
|
|
9212
|
-
|
|
9499
|
+
flushBatches(ctx);
|
|
9213
9500
|
this.meshCache.freeTransient();
|
|
9214
9501
|
}
|
|
9215
9502
|
resize(dims) {
|
|
@@ -9243,6 +9530,10 @@ var WeaselRenderer = class {
|
|
|
9243
9530
|
return this.solidBatch;
|
|
9244
9531
|
}
|
|
9245
9532
|
/** @internal */
|
|
9533
|
+
_imageBatch() {
|
|
9534
|
+
return this.imageBatch;
|
|
9535
|
+
}
|
|
9536
|
+
/** @internal */
|
|
9246
9537
|
_textSdf() {
|
|
9247
9538
|
return this.textSdf;
|
|
9248
9539
|
}
|
|
@@ -9255,6 +9546,10 @@ var WeaselRenderer = class {
|
|
|
9255
9546
|
return this.imageFill;
|
|
9256
9547
|
}
|
|
9257
9548
|
/** @internal */
|
|
9549
|
+
_imageFillVOpacity() {
|
|
9550
|
+
return this.imageFillVOpacity;
|
|
9551
|
+
}
|
|
9552
|
+
/** @internal */
|
|
9258
9553
|
_gradFill() {
|
|
9259
9554
|
return this.gradFill;
|
|
9260
9555
|
}
|
|
@@ -9850,6 +10145,116 @@ function clientToCanvas(canvas, clientX, clientY) {
|
|
|
9850
10145
|
function clientToCanvasRect(rect, clientX, clientY) {
|
|
9851
10146
|
return [clientX - rect.left, clientY - rect.top];
|
|
9852
10147
|
}
|
|
10148
|
+
var LOST_CAPTURE_EVENT = "lostpointercapture";
|
|
10149
|
+
function reportsButtons(down) {
|
|
10150
|
+
return !!down.buttons;
|
|
10151
|
+
}
|
|
10152
|
+
function isMissedRelease(move) {
|
|
10153
|
+
return move.buttons === 0;
|
|
10154
|
+
}
|
|
10155
|
+
function openPointerSession(origin, down, cb, opts = {}) {
|
|
10156
|
+
const pointerId = down.pointerId;
|
|
10157
|
+
const doc = origin.ownerDocument ?? document;
|
|
10158
|
+
const buttonsReported = reportsButtons(down);
|
|
10159
|
+
let active = true;
|
|
10160
|
+
const teardown = () => {
|
|
10161
|
+
active = false;
|
|
10162
|
+
doc.removeEventListener("pointermove", onMove, true);
|
|
10163
|
+
doc.removeEventListener("pointerup", onUp, true);
|
|
10164
|
+
doc.removeEventListener("pointercancel", onPointerCancel, true);
|
|
10165
|
+
doc.removeEventListener("pointerdown", onRepress, true);
|
|
10166
|
+
origin.removeEventListener(LOST_CAPTURE_EVENT, onLostCapture);
|
|
10167
|
+
if (opts.capture !== false) {
|
|
10168
|
+
try {
|
|
10169
|
+
origin.releasePointerCapture?.(pointerId);
|
|
10170
|
+
} catch {
|
|
10171
|
+
}
|
|
10172
|
+
}
|
|
10173
|
+
};
|
|
10174
|
+
const mine = (e) => e.pointerId === pointerId;
|
|
10175
|
+
const end = (e) => {
|
|
10176
|
+
if (!active) return;
|
|
10177
|
+
teardown();
|
|
10178
|
+
cb.onEnd?.(e);
|
|
10179
|
+
};
|
|
10180
|
+
const abort = (reason) => {
|
|
10181
|
+
if (!active) return;
|
|
10182
|
+
teardown();
|
|
10183
|
+
cb.onCancel?.(reason);
|
|
10184
|
+
};
|
|
10185
|
+
function onMove(e) {
|
|
10186
|
+
if (!active || !mine(e)) return;
|
|
10187
|
+
if (buttonsReported && isMissedRelease(e)) {
|
|
10188
|
+
end(e);
|
|
10189
|
+
return;
|
|
10190
|
+
}
|
|
10191
|
+
cb.onMove?.(e);
|
|
10192
|
+
}
|
|
10193
|
+
function onUp(e) {
|
|
10194
|
+
if (mine(e)) end(e);
|
|
10195
|
+
}
|
|
10196
|
+
function onPointerCancel(e) {
|
|
10197
|
+
if (mine(e)) abort("pointercancel");
|
|
10198
|
+
}
|
|
10199
|
+
function onRepress(e) {
|
|
10200
|
+
if (mine(e)) abort("superseded");
|
|
10201
|
+
}
|
|
10202
|
+
function onLostCapture(e) {
|
|
10203
|
+
if (e.pointerId !== pointerId) return;
|
|
10204
|
+
if (!origin.isConnected) abort("lostcapture");
|
|
10205
|
+
}
|
|
10206
|
+
if (opts.capture !== false) {
|
|
10207
|
+
try {
|
|
10208
|
+
origin.setPointerCapture?.(pointerId);
|
|
10209
|
+
} catch {
|
|
10210
|
+
}
|
|
10211
|
+
}
|
|
10212
|
+
doc.addEventListener("pointermove", onMove, true);
|
|
10213
|
+
doc.addEventListener("pointerup", onUp, true);
|
|
10214
|
+
doc.addEventListener("pointercancel", onPointerCancel, true);
|
|
10215
|
+
doc.addEventListener("pointerdown", onRepress, true);
|
|
10216
|
+
origin.addEventListener(LOST_CAPTURE_EVENT, onLostCapture);
|
|
10217
|
+
return {
|
|
10218
|
+
pointerId,
|
|
10219
|
+
get active() {
|
|
10220
|
+
return active;
|
|
10221
|
+
},
|
|
10222
|
+
cancel: () => abort("aborted")
|
|
10223
|
+
};
|
|
10224
|
+
}
|
|
10225
|
+
function startThresholdDrag(e, opts) {
|
|
10226
|
+
const startX = e.clientX;
|
|
10227
|
+
const startY = e.clientY;
|
|
10228
|
+
const threshold = opts.threshold ?? 4;
|
|
10229
|
+
let activated = false;
|
|
10230
|
+
const maybeActivate = (ev) => {
|
|
10231
|
+
if (activated) return;
|
|
10232
|
+
const dx = ev.clientX - startX;
|
|
10233
|
+
const dy = ev.clientY - startY;
|
|
10234
|
+
if (dx * dx + dy * dy < threshold * threshold) return;
|
|
10235
|
+
activated = true;
|
|
10236
|
+
opts.onActivate?.(ev);
|
|
10237
|
+
};
|
|
10238
|
+
const session = openPointerSession(opts.origin ?? e.currentTarget, e, {
|
|
10239
|
+
onMove: (ev) => {
|
|
10240
|
+
maybeActivate(ev);
|
|
10241
|
+
if (activated) opts.onMove(ev);
|
|
10242
|
+
},
|
|
10243
|
+
onEnd: (ev) => {
|
|
10244
|
+
if (activated) opts.onCommit(ev);
|
|
10245
|
+
else opts.onClick?.(ev);
|
|
10246
|
+
},
|
|
10247
|
+
onCancel: () => {
|
|
10248
|
+
opts.onCancel?.();
|
|
10249
|
+
}
|
|
10250
|
+
});
|
|
10251
|
+
return {
|
|
10252
|
+
isDragging: () => activated,
|
|
10253
|
+
cancel: () => {
|
|
10254
|
+
session.cancel();
|
|
10255
|
+
}
|
|
10256
|
+
};
|
|
10257
|
+
}
|
|
9853
10258
|
var BASE_PX = {
|
|
9854
10259
|
handle: 8,
|
|
9855
10260
|
anchor: 8,
|
|
@@ -11609,6 +12014,28 @@ var cloneAction = {
|
|
|
11609
12014
|
},
|
|
11610
12015
|
enabled: () => true
|
|
11611
12016
|
};
|
|
12017
|
+
function createVelocityTracker() {
|
|
12018
|
+
let samples = [];
|
|
12019
|
+
return {
|
|
12020
|
+
record(dx, dy, t) {
|
|
12021
|
+
samples.push({ dx, dy, t });
|
|
12022
|
+
const cutoff = t - 100;
|
|
12023
|
+
samples = samples.filter((s) => s.t >= cutoff);
|
|
12024
|
+
},
|
|
12025
|
+
getVelocity() {
|
|
12026
|
+
const s = samples;
|
|
12027
|
+
if (s.length < 2) return { vx: 0, vy: 0 };
|
|
12028
|
+
const dt = s[s.length - 1].t - s[0].t;
|
|
12029
|
+
if (dt === 0) return { vx: 0, vy: 0 };
|
|
12030
|
+
const totalDx = s.slice(1).reduce((acc, p) => acc + p.dx, 0);
|
|
12031
|
+
const totalDy = s.slice(1).reduce((acc, p) => acc + p.dy, 0);
|
|
12032
|
+
return { vx: totalDx / dt, vy: totalDy / dt };
|
|
12033
|
+
},
|
|
12034
|
+
reset() {
|
|
12035
|
+
samples = [];
|
|
12036
|
+
}
|
|
12037
|
+
};
|
|
12038
|
+
}
|
|
11612
12039
|
var viewportDragPanAction = {
|
|
11613
12040
|
id: "viewport.dragPan",
|
|
11614
12041
|
label: "Drag to pan viewport",
|
|
@@ -11626,17 +12053,37 @@ var viewportDragPanAction = {
|
|
|
11626
12053
|
requires: ["view"],
|
|
11627
12054
|
invoker: {
|
|
11628
12055
|
timing: "ongoing",
|
|
11629
|
-
start(ctx) {
|
|
12056
|
+
start(ctx, opts) {
|
|
11630
12057
|
const view = ctx.deps.view;
|
|
11631
12058
|
if (!view) return {};
|
|
11632
12059
|
const startView = view.get();
|
|
11633
|
-
const
|
|
12060
|
+
const params = resolveParams(opts?.params) ?? {};
|
|
12061
|
+
const inertia = params.inertia === false ? void 0 : params.inertia;
|
|
12062
|
+
const scratch = {
|
|
12063
|
+
startView,
|
|
12064
|
+
view,
|
|
12065
|
+
axis: params.axis ?? "both",
|
|
12066
|
+
inertia,
|
|
12067
|
+
// Only track when a coast could actually happen, so the common
|
|
12068
|
+
// no-inertia drag does no per-move work.
|
|
12069
|
+
tracker: inertia && view.decay ? createVelocityTracker() : void 0,
|
|
12070
|
+
lastScreen: { x: 0, y: 0 }
|
|
12071
|
+
};
|
|
11634
12072
|
return {
|
|
11635
12073
|
kind: "pan",
|
|
11636
12074
|
onMove(moveCtx) {
|
|
11637
12075
|
if (!moveCtx.drag) return;
|
|
11638
12076
|
const screen = moveCtx.drag.screenDelta ?? moveCtx.drag.delta;
|
|
11639
|
-
const
|
|
12077
|
+
const screenDx = scratch.axis === "y" ? 0 : screen.x;
|
|
12078
|
+
const screenDy = scratch.axis === "x" ? 0 : screen.y;
|
|
12079
|
+
if (scratch.tracker) {
|
|
12080
|
+
scratch.tracker.record(
|
|
12081
|
+
screenDx - scratch.lastScreen.x,
|
|
12082
|
+
screenDy - scratch.lastScreen.y,
|
|
12083
|
+
performance.now()
|
|
12084
|
+
);
|
|
12085
|
+
scratch.lastScreen = { x: screenDx, y: screenDy };
|
|
12086
|
+
}
|
|
11640
12087
|
const sv = scratch.startView;
|
|
11641
12088
|
scratch.view.set({
|
|
11642
12089
|
...sv,
|
|
@@ -11644,7 +12091,24 @@ var viewportDragPanAction = {
|
|
|
11644
12091
|
y: sv.y - screenDy / sv.scale.y
|
|
11645
12092
|
});
|
|
11646
12093
|
},
|
|
11647
|
-
onEnd() {
|
|
12094
|
+
onEnd(_endCtx, reason) {
|
|
12095
|
+
const { tracker, inertia: inertia2, view: v } = scratch;
|
|
12096
|
+
if (reason === "cancel" || !tracker || !inertia2 || !v.decay) return;
|
|
12097
|
+
const { vx, vy } = tracker.getVelocity();
|
|
12098
|
+
const scale2 = scratch.startView.scale;
|
|
12099
|
+
v.decay({
|
|
12100
|
+
// Screen px/ms → world units/ms, matching the onMove conversion.
|
|
12101
|
+
velocity: { vx: -vx / scale2.x, vy: -vy / scale2.y },
|
|
12102
|
+
friction: inertia2.friction,
|
|
12103
|
+
minSpeed: inertia2.minSpeed,
|
|
12104
|
+
boundary: inertia2.boundary,
|
|
12105
|
+
viewBounds: inertia2.bounds,
|
|
12106
|
+
initialPosition: { x: v.get().x, y: v.get().y },
|
|
12107
|
+
onTick: (dx, dy) => {
|
|
12108
|
+
const cur = v.get();
|
|
12109
|
+
v.set({ ...cur, x: cur.x + dx, y: cur.y + dy });
|
|
12110
|
+
}
|
|
12111
|
+
});
|
|
11648
12112
|
}
|
|
11649
12113
|
};
|
|
11650
12114
|
}
|
|
@@ -11745,6 +12209,52 @@ function makeViewportZoomAction(opts = {}) {
|
|
|
11745
12209
|
};
|
|
11746
12210
|
}
|
|
11747
12211
|
makeViewportZoomAction();
|
|
12212
|
+
var viewportWheelPanAction = {
|
|
12213
|
+
id: "viewport.wheelPan",
|
|
12214
|
+
label: "Pan (wheel)",
|
|
12215
|
+
group: "viewport",
|
|
12216
|
+
/**
|
|
12217
|
+
* Plain wheel → pan; Shift+wheel → horizontal pan (axis swap).
|
|
12218
|
+
* Cmd+wheel is claimed by `viewportZoomAction`. The matcher's strict
|
|
12219
|
+
* modifier check keeps the bindings exclusive: omitting `mods` forbids
|
|
12220
|
+
* any modifier, and `mods: { shift: true }` forbids the others.
|
|
12221
|
+
*/
|
|
12222
|
+
defaultBinding: [
|
|
12223
|
+
{ spec: { kind: "wheel" }, opts: {} },
|
|
12224
|
+
{ spec: { kind: "wheel", mods: { shift: true } }, opts: { params: { swapAxis: true } } }
|
|
12225
|
+
],
|
|
12226
|
+
requires: ["view"],
|
|
12227
|
+
invoker: {
|
|
12228
|
+
timing: "immediate",
|
|
12229
|
+
run(deps, params) {
|
|
12230
|
+
const view = deps.view;
|
|
12231
|
+
if (!view) return;
|
|
12232
|
+
const axis = params?.axis ?? "both";
|
|
12233
|
+
const deltaX = params?.deltaX ?? 0;
|
|
12234
|
+
const deltaY = params?.deltaY ?? 0;
|
|
12235
|
+
const current = view.get();
|
|
12236
|
+
const swap = params?.swapAxis === true;
|
|
12237
|
+
const dx = swap ? (deltaX !== 0 ? deltaX : deltaY) / current.scale.x : deltaX / current.scale.x;
|
|
12238
|
+
const dy = swap ? 0 : deltaY / current.scale.y;
|
|
12239
|
+
view.set({
|
|
12240
|
+
...current,
|
|
12241
|
+
x: current.x + (axis === "y" ? 0 : dx),
|
|
12242
|
+
y: current.y + (axis === "x" ? 0 : dy)
|
|
12243
|
+
});
|
|
12244
|
+
}
|
|
12245
|
+
},
|
|
12246
|
+
enabled: () => true
|
|
12247
|
+
};
|
|
12248
|
+
function makeViewportWheelPanAction(opts = {}) {
|
|
12249
|
+
const axis = opts.axis ?? "both";
|
|
12250
|
+
return {
|
|
12251
|
+
...viewportWheelPanAction,
|
|
12252
|
+
defaultBinding: [
|
|
12253
|
+
{ spec: { kind: "wheel" }, opts: { params: { axis } } },
|
|
12254
|
+
{ spec: { kind: "wheel", mods: { shift: true } }, opts: { params: { swapAxis: true, axis } } }
|
|
12255
|
+
]
|
|
12256
|
+
};
|
|
12257
|
+
}
|
|
11748
12258
|
function bodyPredicate(fn) {
|
|
11749
12259
|
return Object.assign(fn, { readsAffordance: false });
|
|
11750
12260
|
}
|
|
@@ -16120,7 +16630,7 @@ function withViewDeps(base, overlay) {
|
|
|
16120
16630
|
};
|
|
16121
16631
|
}
|
|
16122
16632
|
function computeMultiTouchGeometry(positions) {
|
|
16123
|
-
const pts = [...positions
|
|
16633
|
+
const pts = [...positions];
|
|
16124
16634
|
if (pts.length < 2) {
|
|
16125
16635
|
return { centroid: { x: 0, y: 0 }, spread: 0 };
|
|
16126
16636
|
}
|
|
@@ -16247,13 +16757,13 @@ function useGestureDispatcher(opts) {
|
|
|
16247
16757
|
return result;
|
|
16248
16758
|
};
|
|
16249
16759
|
const heldKeys = /* @__PURE__ */ new Set();
|
|
16250
|
-
const
|
|
16251
|
-
const
|
|
16760
|
+
const held = /* @__PURE__ */ new Map();
|
|
16761
|
+
const heldGeometry = () => computeMultiTouchGeometry(
|
|
16762
|
+
[...held.values()].map((p) => p.pos)
|
|
16763
|
+
);
|
|
16252
16764
|
let multiTouchStart = null;
|
|
16253
16765
|
const TAP_THRESHOLD_PX = 8;
|
|
16254
16766
|
const DRAG_THRESHOLD_PX = 4;
|
|
16255
|
-
const bufferedDown = /* @__PURE__ */ new Map();
|
|
16256
|
-
const lastPointerDown = /* @__PURE__ */ new Map();
|
|
16257
16767
|
const LONG_PRESS_MS = 500;
|
|
16258
16768
|
const longPressTimers = /* @__PURE__ */ new Map();
|
|
16259
16769
|
const cancelLongPress = (pointerId) => {
|
|
@@ -16268,7 +16778,7 @@ function useGestureDispatcher(opts) {
|
|
|
16268
16778
|
longPressTimers.clear();
|
|
16269
16779
|
};
|
|
16270
16780
|
const fireLongPress = (pointerId) => {
|
|
16271
|
-
const down =
|
|
16781
|
+
const down = held.get(pointerId)?.down;
|
|
16272
16782
|
if (!down) return;
|
|
16273
16783
|
const shared = {
|
|
16274
16784
|
target: down.target,
|
|
@@ -16390,13 +16900,8 @@ function useGestureDispatcher(opts) {
|
|
|
16390
16900
|
};
|
|
16391
16901
|
const onPointerDown = (e) => {
|
|
16392
16902
|
if ((e.button ?? 0) !== 0) return;
|
|
16903
|
+
if (!canvas) return;
|
|
16393
16904
|
routeDown(e.pointerId, e.clientX, e.clientY);
|
|
16394
|
-
activePointers.add(e.pointerId);
|
|
16395
|
-
pointerPositions.set(e.pointerId, { x: e.clientX, y: e.clientY });
|
|
16396
|
-
try {
|
|
16397
|
-
canvas?.setPointerCapture?.(e.pointerId);
|
|
16398
|
-
} catch {
|
|
16399
|
-
}
|
|
16400
16905
|
const worldPoint = { x: e.clientX, y: e.clientY };
|
|
16401
16906
|
const affordance = target().affordanceAt?.(worldPoint) ?? void 0;
|
|
16402
16907
|
const body = target().classifyTarget?.(worldPoint);
|
|
@@ -16420,23 +16925,35 @@ function useGestureDispatcher(opts) {
|
|
|
16420
16925
|
...bodyTarget !== void 0 ? { bodyTarget } : {},
|
|
16421
16926
|
...bodyKind !== void 0 ? { bodyKind } : {}
|
|
16422
16927
|
};
|
|
16423
|
-
|
|
16424
|
-
|
|
16425
|
-
|
|
16426
|
-
|
|
16427
|
-
|
|
16428
|
-
|
|
16429
|
-
|
|
16430
|
-
|
|
16431
|
-
|
|
16432
|
-
|
|
16433
|
-
|
|
16434
|
-
|
|
16435
|
-
|
|
16436
|
-
|
|
16437
|
-
|
|
16928
|
+
held.set(e.pointerId, {
|
|
16929
|
+
session: openPointerSession(canvas, e, {
|
|
16930
|
+
onMove: onPointerMove,
|
|
16931
|
+
onEnd: onPointerUp,
|
|
16932
|
+
onCancel: () => {
|
|
16933
|
+
onPointerCancel(e.pointerId);
|
|
16934
|
+
}
|
|
16935
|
+
}),
|
|
16936
|
+
pos: { x: e.clientX, y: e.clientY },
|
|
16937
|
+
// Deferred until the first past-threshold pointermove: a bare
|
|
16938
|
+
// press-and-release should fire `click`, not start a drag action.
|
|
16939
|
+
buffered: { ev, clientX: e.clientX, clientY: e.clientY },
|
|
16940
|
+
down: {
|
|
16941
|
+
target: e.target,
|
|
16942
|
+
clientX: e.clientX,
|
|
16943
|
+
clientY: e.clientY,
|
|
16944
|
+
worldX: w.x,
|
|
16945
|
+
worldY: w.y,
|
|
16946
|
+
affordance,
|
|
16947
|
+
bodyTarget,
|
|
16948
|
+
bodyKind,
|
|
16949
|
+
altKey: e.altKey,
|
|
16950
|
+
ctrlKey: e.ctrlKey,
|
|
16951
|
+
metaKey: e.metaKey,
|
|
16952
|
+
shiftKey: e.shiftKey
|
|
16953
|
+
}
|
|
16438
16954
|
});
|
|
16439
|
-
|
|
16955
|
+
dispatch2({ ...ev, stage: "press" });
|
|
16956
|
+
if ((e.pointerType === "touch" || e.pointerType === "pen") && held.size === 1) {
|
|
16440
16957
|
cancelLongPress(e.pointerId);
|
|
16441
16958
|
longPressTimers.set(
|
|
16442
16959
|
e.pointerId,
|
|
@@ -16447,18 +16964,18 @@ function useGestureDispatcher(opts) {
|
|
|
16447
16964
|
}, LONG_PRESS_MS)
|
|
16448
16965
|
);
|
|
16449
16966
|
}
|
|
16450
|
-
if (
|
|
16967
|
+
if (held.size >= 2) {
|
|
16451
16968
|
cancelAllLongPress();
|
|
16452
|
-
for (const
|
|
16453
|
-
const { centroid, spread } =
|
|
16969
|
+
for (const p of held.values()) p.buffered = null;
|
|
16970
|
+
const { centroid, spread } = heldGeometry();
|
|
16454
16971
|
if (!multiTouchStart) {
|
|
16455
|
-
multiTouchStart = { fingers:
|
|
16972
|
+
multiTouchStart = { fingers: held.size, centroid: { ...centroid } };
|
|
16456
16973
|
} else {
|
|
16457
|
-
multiTouchStart.fingers =
|
|
16974
|
+
multiTouchStart.fingers = held.size;
|
|
16458
16975
|
}
|
|
16459
16976
|
const mt = {
|
|
16460
16977
|
kind: "multitouch",
|
|
16461
|
-
fingers:
|
|
16978
|
+
fingers: held.size,
|
|
16462
16979
|
altKey: e.altKey,
|
|
16463
16980
|
ctrlKey: e.ctrlKey,
|
|
16464
16981
|
metaKey: e.metaKey,
|
|
@@ -16471,25 +16988,24 @@ function useGestureDispatcher(opts) {
|
|
|
16471
16988
|
};
|
|
16472
16989
|
const onPointerMove = (e) => {
|
|
16473
16990
|
routeAt(e.pointerId, e.clientX, e.clientY);
|
|
16474
|
-
|
|
16475
|
-
|
|
16476
|
-
|
|
16477
|
-
|
|
16478
|
-
if (buffered) {
|
|
16991
|
+
const rec = held.get(e.pointerId);
|
|
16992
|
+
if (rec) rec.pos = { x: e.clientX, y: e.clientY };
|
|
16993
|
+
const buffered = rec?.buffered;
|
|
16994
|
+
if (rec && buffered) {
|
|
16479
16995
|
const dx = e.clientX - buffered.clientX;
|
|
16480
16996
|
const dy = e.clientY - buffered.clientY;
|
|
16481
16997
|
if (Math.hypot(dx, dy) >= DRAG_THRESHOLD_PX) {
|
|
16482
|
-
|
|
16998
|
+
rec.buffered = null;
|
|
16483
16999
|
cancelLongPress(e.pointerId);
|
|
16484
17000
|
dispatch2(buffered.ev);
|
|
16485
17001
|
}
|
|
16486
17002
|
}
|
|
16487
|
-
const mtGestureId = `multitouch-${
|
|
16488
|
-
if (
|
|
16489
|
-
const { centroid, spread } =
|
|
17003
|
+
const mtGestureId = `multitouch-${held.size}`;
|
|
17004
|
+
if (held.size >= 2 && dispatcherNow().inFlight().has(mtGestureId)) {
|
|
17005
|
+
const { centroid, spread } = heldGeometry();
|
|
16490
17006
|
const mtEv = {
|
|
16491
17007
|
kind: "multitouch",
|
|
16492
|
-
fingers:
|
|
17008
|
+
fingers: held.size,
|
|
16493
17009
|
altKey: e.altKey,
|
|
16494
17010
|
ctrlKey: e.ctrlKey,
|
|
16495
17011
|
metaKey: e.metaKey,
|
|
@@ -16561,7 +17077,7 @@ function useGestureDispatcher(opts) {
|
|
|
16561
17077
|
}
|
|
16562
17078
|
function resolveHoverCursor() {
|
|
16563
17079
|
if (!canvas || !lastHover) return;
|
|
16564
|
-
if (
|
|
17080
|
+
if (held.size > 0 || dispatcherNow().inFlight().size > 0) {
|
|
16565
17081
|
applyHoverCursor(dispatcherNow().inFlightCursor());
|
|
16566
17082
|
return;
|
|
16567
17083
|
}
|
|
@@ -16609,6 +17125,10 @@ function useGestureDispatcher(opts) {
|
|
|
16609
17125
|
if (!disposed) refreshHoverCursor();
|
|
16610
17126
|
}, 0);
|
|
16611
17127
|
};
|
|
17128
|
+
const onHoverMove = (e) => {
|
|
17129
|
+
if (held.has(e.pointerId)) return;
|
|
17130
|
+
onPointerMove(e);
|
|
17131
|
+
};
|
|
16612
17132
|
const onHoverPointerLeave = () => {
|
|
16613
17133
|
lastHover = null;
|
|
16614
17134
|
paintedCursorRef.current?.()?.clearPointer();
|
|
@@ -16617,20 +17137,21 @@ function useGestureDispatcher(opts) {
|
|
|
16617
17137
|
const onPointerUp = (e) => {
|
|
16618
17138
|
routeAt(e.pointerId, e.clientX, e.clientY);
|
|
16619
17139
|
cancelLongPress(e.pointerId);
|
|
16620
|
-
const prevSize =
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
const staysUnderThreshold =
|
|
16624
|
-
if (prevSize >= 2 &&
|
|
17140
|
+
const prevSize = held.size;
|
|
17141
|
+
const rec = held.get(e.pointerId);
|
|
17142
|
+
held.delete(e.pointerId);
|
|
17143
|
+
const staysUnderThreshold = rec?.buffered != null;
|
|
17144
|
+
if (prevSize >= 2 && held.size < 2) {
|
|
16625
17145
|
const mtGestureId = `multitouch-${prevSize}`;
|
|
16626
17146
|
if (dispatcherNow().inFlight().has(mtGestureId)) {
|
|
16627
17147
|
dispatcherNow().cancelAll("commit");
|
|
16628
17148
|
}
|
|
16629
17149
|
const start = multiTouchStart;
|
|
16630
17150
|
if (start) {
|
|
16631
|
-
const
|
|
16632
|
-
|
|
16633
|
-
|
|
17151
|
+
const { centroid } = computeMultiTouchGeometry([
|
|
17152
|
+
...[...held.values()].map((p) => p.pos),
|
|
17153
|
+
{ x: e.clientX, y: e.clientY }
|
|
17154
|
+
]);
|
|
16634
17155
|
const dx = centroid.x - start.centroid.x;
|
|
16635
17156
|
const dy = centroid.y - start.centroid.y;
|
|
16636
17157
|
if (Math.hypot(dx, dy) <= TAP_THRESHOLD_PX) {
|
|
@@ -16647,8 +17168,7 @@ function useGestureDispatcher(opts) {
|
|
|
16647
17168
|
multiTouchStart = null;
|
|
16648
17169
|
}
|
|
16649
17170
|
}
|
|
16650
|
-
const
|
|
16651
|
-
const movedDuringDrag = downForClick ? downForClick.clientX !== e.clientX || downForClick.clientY !== e.clientY : true;
|
|
17171
|
+
const movedDuringDrag = rec ? rec.down.clientX !== e.clientX || rec.down.clientY !== e.clientY : true;
|
|
16652
17172
|
const hadDragInFlight = dispatcherNow().inFlight().has(pointerGestureId(e.pointerId)) && movedDuringDrag;
|
|
16653
17173
|
const wUp = toWorld2(e.clientX, e.clientY);
|
|
16654
17174
|
const ev = {
|
|
@@ -16664,8 +17184,7 @@ function useGestureDispatcher(opts) {
|
|
|
16664
17184
|
shiftKey: e.shiftKey
|
|
16665
17185
|
};
|
|
16666
17186
|
dispatch2(ev);
|
|
16667
|
-
const down =
|
|
16668
|
-
lastPointerDown.delete(e.pointerId);
|
|
17187
|
+
const down = rec?.down;
|
|
16669
17188
|
if (!hadDragInFlight && staysUnderThreshold && down) {
|
|
16670
17189
|
const wClick = toWorld2(e.clientX, e.clientY);
|
|
16671
17190
|
const clickEv = {
|
|
@@ -16722,24 +17241,24 @@ function useGestureDispatcher(opts) {
|
|
|
16722
17241
|
if (!disposed) refreshHoverCursor();
|
|
16723
17242
|
}, 0);
|
|
16724
17243
|
};
|
|
16725
|
-
const onPointerCancel = (
|
|
16726
|
-
|
|
16727
|
-
|
|
16728
|
-
|
|
16729
|
-
|
|
16730
|
-
|
|
16731
|
-
|
|
17244
|
+
const onPointerCancel = (pointerId) => {
|
|
17245
|
+
if (disposed) return;
|
|
17246
|
+
const rec = held.get(pointerId);
|
|
17247
|
+
if (!rec) return;
|
|
17248
|
+
held.delete(pointerId);
|
|
17249
|
+
routeAt(pointerId, rec.pos.x, rec.pos.y);
|
|
17250
|
+
cancelLongPress(pointerId);
|
|
16732
17251
|
multiTouchStart = null;
|
|
16733
17252
|
const ev = {
|
|
16734
17253
|
kind: "pointercancel",
|
|
16735
|
-
pointerId
|
|
16736
|
-
altKey:
|
|
16737
|
-
ctrlKey:
|
|
16738
|
-
metaKey:
|
|
16739
|
-
shiftKey:
|
|
17254
|
+
pointerId,
|
|
17255
|
+
altKey: rec.down.altKey,
|
|
17256
|
+
ctrlKey: rec.down.ctrlKey,
|
|
17257
|
+
metaKey: rec.down.metaKey,
|
|
17258
|
+
shiftKey: rec.down.shiftKey
|
|
16740
17259
|
};
|
|
16741
17260
|
dispatch2(ev);
|
|
16742
|
-
routeRelease(
|
|
17261
|
+
routeRelease(pointerId);
|
|
16743
17262
|
};
|
|
16744
17263
|
const onContextMenu = (e) => {
|
|
16745
17264
|
e.preventDefault();
|
|
@@ -16827,9 +17346,7 @@ function useGestureDispatcher(opts) {
|
|
|
16827
17346
|
canvas?.addEventListener("pointerleave", onHoverPointerLeave);
|
|
16828
17347
|
canvas?.addEventListener("wheel", onWheel, { passive: false });
|
|
16829
17348
|
canvas?.addEventListener("pointerdown", onPointerDown);
|
|
16830
|
-
canvas?.addEventListener("pointermove",
|
|
16831
|
-
canvas?.addEventListener("pointerup", onPointerUp);
|
|
16832
|
-
canvas?.addEventListener("pointercancel", onPointerCancel);
|
|
17349
|
+
canvas?.addEventListener("pointermove", onHoverMove);
|
|
16833
17350
|
canvas?.addEventListener("contextmenu", onContextMenu);
|
|
16834
17351
|
canvas?.addEventListener("dragenter", onDragOver);
|
|
16835
17352
|
canvas?.addEventListener("dragover", onDragOver);
|
|
@@ -16847,9 +17364,7 @@ function useGestureDispatcher(opts) {
|
|
|
16847
17364
|
canvas?.removeEventListener("pointerleave", onHoverPointerLeave);
|
|
16848
17365
|
canvas?.removeEventListener("wheel", onWheel);
|
|
16849
17366
|
canvas?.removeEventListener("pointerdown", onPointerDown);
|
|
16850
|
-
canvas?.removeEventListener("pointermove",
|
|
16851
|
-
canvas?.removeEventListener("pointerup", onPointerUp);
|
|
16852
|
-
canvas?.removeEventListener("pointercancel", onPointerCancel);
|
|
17367
|
+
canvas?.removeEventListener("pointermove", onHoverMove);
|
|
16853
17368
|
canvas?.removeEventListener("contextmenu", onContextMenu);
|
|
16854
17369
|
canvas?.removeEventListener("dragenter", onDragOver);
|
|
16855
17370
|
canvas?.removeEventListener("dragover", onDragOver);
|
|
@@ -16860,10 +17375,138 @@ function useGestureDispatcher(opts) {
|
|
|
16860
17375
|
clearHoverCursor();
|
|
16861
17376
|
cancelAllLongPress();
|
|
16862
17377
|
disposed = true;
|
|
17378
|
+
for (const p of held.values()) p.session.cancel();
|
|
17379
|
+
held.clear();
|
|
16863
17380
|
for (const d of allDispatchers()) d.cancelAll("cancel");
|
|
16864
17381
|
};
|
|
16865
17382
|
}, [enabled, keyboard, canvasRef]);
|
|
16866
17383
|
}
|
|
17384
|
+
var SPRING_DAMPING = 0.5;
|
|
17385
|
+
function useDecayLoop() {
|
|
17386
|
+
const stateRef = useRef(null);
|
|
17387
|
+
const frameLoop = useVisibleRaf(
|
|
17388
|
+
(now) => {
|
|
17389
|
+
tick(now);
|
|
17390
|
+
},
|
|
17391
|
+
{
|
|
17392
|
+
// Coasting does not continue while suspended: dropping `lastTime` makes
|
|
17393
|
+
// the resuming frame seed a fresh interval instead of applying an hour of
|
|
17394
|
+
// friction at once, which would end the decay before it was seen.
|
|
17395
|
+
onResume: useCallback(() => {
|
|
17396
|
+
if (stateRef.current) stateRef.current.lastTime = null;
|
|
17397
|
+
}, [])
|
|
17398
|
+
}
|
|
17399
|
+
);
|
|
17400
|
+
const cancel = useCallback(() => {
|
|
17401
|
+
frameLoop.cancel();
|
|
17402
|
+
stateRef.current = null;
|
|
17403
|
+
}, [frameLoop]);
|
|
17404
|
+
const tick = useCallback((now) => {
|
|
17405
|
+
const s = stateRef.current;
|
|
17406
|
+
if (!s) return;
|
|
17407
|
+
if (s.lastTime === null) {
|
|
17408
|
+
s.lastTime = now;
|
|
17409
|
+
frameLoop.request();
|
|
17410
|
+
return;
|
|
17411
|
+
}
|
|
17412
|
+
const dt = Math.min(now - s.lastTime, 64);
|
|
17413
|
+
s.lastTime = now;
|
|
17414
|
+
const f = Math.pow(s.friction, dt / 16.67);
|
|
17415
|
+
s.vx *= f;
|
|
17416
|
+
s.vy *= f;
|
|
17417
|
+
const speed = Math.sqrt(s.vx * s.vx + s.vy * s.vy);
|
|
17418
|
+
if (speed < s.minSpeed) {
|
|
17419
|
+
stateRef.current = null;
|
|
17420
|
+
frameLoop.cancel();
|
|
17421
|
+
s.onEnd?.();
|
|
17422
|
+
return;
|
|
17423
|
+
}
|
|
17424
|
+
let dx = s.vx * dt;
|
|
17425
|
+
let dy = s.vy * dt;
|
|
17426
|
+
if (s.viewBounds && s.boundary) {
|
|
17427
|
+
const { minX, maxX, minY, maxY } = s.viewBounds;
|
|
17428
|
+
const newX = s.posX + dx;
|
|
17429
|
+
const newY = s.posY + dy;
|
|
17430
|
+
if (s.boundary === "stop") {
|
|
17431
|
+
if (minX !== void 0 && newX < minX) {
|
|
17432
|
+
dx = minX - s.posX;
|
|
17433
|
+
s.vx = 0;
|
|
17434
|
+
} else if (maxX !== void 0 && newX > maxX) {
|
|
17435
|
+
dx = maxX - s.posX;
|
|
17436
|
+
s.vx = 0;
|
|
17437
|
+
}
|
|
17438
|
+
if (minY !== void 0 && newY < minY) {
|
|
17439
|
+
dy = minY - s.posY;
|
|
17440
|
+
s.vy = 0;
|
|
17441
|
+
} else if (maxY !== void 0 && newY > maxY) {
|
|
17442
|
+
dy = maxY - s.posY;
|
|
17443
|
+
s.vy = 0;
|
|
17444
|
+
}
|
|
17445
|
+
} else if (s.boundary === "spring") {
|
|
17446
|
+
if (minX !== void 0 && newX < minX) {
|
|
17447
|
+
dx = minX - s.posX;
|
|
17448
|
+
s.vx = Math.abs(s.vx) * SPRING_DAMPING;
|
|
17449
|
+
} else if (maxX !== void 0 && newX > maxX) {
|
|
17450
|
+
dx = maxX - s.posX;
|
|
17451
|
+
s.vx = -Math.abs(s.vx) * SPRING_DAMPING;
|
|
17452
|
+
}
|
|
17453
|
+
if (minY !== void 0 && newY < minY) {
|
|
17454
|
+
dy = minY - s.posY;
|
|
17455
|
+
s.vy = Math.abs(s.vy) * SPRING_DAMPING;
|
|
17456
|
+
} else if (maxY !== void 0 && newY > maxY) {
|
|
17457
|
+
dy = maxY - s.posY;
|
|
17458
|
+
s.vy = -Math.abs(s.vy) * SPRING_DAMPING;
|
|
17459
|
+
}
|
|
17460
|
+
} else {
|
|
17461
|
+
if (minX !== void 0 && newX < minX) {
|
|
17462
|
+
dx = minX - s.posX;
|
|
17463
|
+
s.vx = Math.abs(s.vx);
|
|
17464
|
+
} else if (maxX !== void 0 && newX > maxX) {
|
|
17465
|
+
dx = maxX - s.posX;
|
|
17466
|
+
s.vx = -Math.abs(s.vx);
|
|
17467
|
+
}
|
|
17468
|
+
if (minY !== void 0 && newY < minY) {
|
|
17469
|
+
dy = minY - s.posY;
|
|
17470
|
+
s.vy = Math.abs(s.vy);
|
|
17471
|
+
} else if (maxY !== void 0 && newY > maxY) {
|
|
17472
|
+
dy = maxY - s.posY;
|
|
17473
|
+
s.vy = -Math.abs(s.vy);
|
|
17474
|
+
}
|
|
17475
|
+
}
|
|
17476
|
+
s.posX += dx;
|
|
17477
|
+
s.posY += dy;
|
|
17478
|
+
}
|
|
17479
|
+
s.onTick(dx, dy);
|
|
17480
|
+
frameLoop.request();
|
|
17481
|
+
}, [frameLoop]);
|
|
17482
|
+
const start = useCallback((config) => {
|
|
17483
|
+
cancel();
|
|
17484
|
+
const { velocity, friction = 0.92, minSpeed = 0.01, viewBounds, boundary, initialPosition, onTick, onEnd } = config;
|
|
17485
|
+
const speed = Math.sqrt(velocity.vx ** 2 + velocity.vy ** 2);
|
|
17486
|
+
if (speed < minSpeed) {
|
|
17487
|
+
onEnd?.();
|
|
17488
|
+
return;
|
|
17489
|
+
}
|
|
17490
|
+
stateRef.current = {
|
|
17491
|
+
vx: velocity.vx,
|
|
17492
|
+
vy: velocity.vy,
|
|
17493
|
+
friction,
|
|
17494
|
+
minSpeed,
|
|
17495
|
+
lastTime: null,
|
|
17496
|
+
posX: initialPosition?.x ?? 0,
|
|
17497
|
+
posY: initialPosition?.y ?? 0,
|
|
17498
|
+
viewBounds,
|
|
17499
|
+
boundary,
|
|
17500
|
+
onTick,
|
|
17501
|
+
onEnd
|
|
17502
|
+
};
|
|
17503
|
+
frameLoop.request();
|
|
17504
|
+
}, [cancel, frameLoop]);
|
|
17505
|
+
useEffect(() => () => {
|
|
17506
|
+
cancel();
|
|
17507
|
+
}, [cancel]);
|
|
17508
|
+
return { start, cancel };
|
|
17509
|
+
}
|
|
16867
17510
|
function dist(a, b) {
|
|
16868
17511
|
return Math.hypot(b.x - a.x, b.y - a.y);
|
|
16869
17512
|
}
|
|
@@ -20485,7 +21128,9 @@ function useRotateTool(adapter, options) {
|
|
|
20485
21128
|
[overlay]
|
|
20486
21129
|
);
|
|
20487
21130
|
}
|
|
20488
|
-
function useHandTool(
|
|
21131
|
+
function useHandTool(opts = {}) {
|
|
21132
|
+
const optsRef = useRef(opts);
|
|
21133
|
+
optsRef.current = opts;
|
|
20489
21134
|
return useMemo(
|
|
20490
21135
|
() => Object.assign(defineViewportTool({
|
|
20491
21136
|
id: "hand",
|
|
@@ -20503,7 +21148,16 @@ function useHandTool(_opts = {}) {
|
|
|
20503
21148
|
// viewportDragPanAction, which also owns the grabbing cursor
|
|
20504
21149
|
// (`Action.activeCursor`) the tool used to declare as an `engaged`
|
|
20505
21150
|
// phase entry.
|
|
20506
|
-
bindings: [{
|
|
21151
|
+
bindings: [{
|
|
21152
|
+
spec: { kind: "drag" },
|
|
21153
|
+
actionId: "viewport.dragPan",
|
|
21154
|
+
opts: {
|
|
21155
|
+
params: () => ({
|
|
21156
|
+
axis: optsRef.current.axis ?? "both",
|
|
21157
|
+
inertia: optsRef.current.inertia
|
|
21158
|
+
})
|
|
21159
|
+
}
|
|
21160
|
+
}]
|
|
20507
21161
|
}),
|
|
20508
21162
|
[]
|
|
20509
21163
|
);
|
|
@@ -21764,6 +22418,20 @@ function projectBounds(b, view) {
|
|
|
21764
22418
|
const [sx, sy] = worldToScreen(b.x, b.y, t);
|
|
21765
22419
|
return { ...b, x: sx, y: sy, width: b.width * view.scale.x, height: b.height * view.scale.y };
|
|
21766
22420
|
}
|
|
22421
|
+
function leavesOf(id, getChildren, isContainer) {
|
|
22422
|
+
if (!isContainer(id)) return [id];
|
|
22423
|
+
const out = [];
|
|
22424
|
+
const visit = (nid) => {
|
|
22425
|
+
const kids = getChildren(nid);
|
|
22426
|
+
if (kids.length === 0) {
|
|
22427
|
+
if (!isContainer(nid)) out.push(nid);
|
|
22428
|
+
return;
|
|
22429
|
+
}
|
|
22430
|
+
for (const k of kids) visit(k);
|
|
22431
|
+
};
|
|
22432
|
+
visit(id);
|
|
22433
|
+
return out;
|
|
22434
|
+
}
|
|
21767
22435
|
function makeContainerAwareBoundsResolver(getPose, getBounds, getChildren, isContainer) {
|
|
21768
22436
|
if (getChildren === void 0 || isContainer === void 0) {
|
|
21769
22437
|
return (id) => {
|
|
@@ -21771,26 +22439,12 @@ function makeContainerAwareBoundsResolver(getPose, getBounds, getChildren, isCon
|
|
|
21771
22439
|
return p === null ? null : getBounds(p);
|
|
21772
22440
|
};
|
|
21773
22441
|
}
|
|
21774
|
-
const leavesOf = (id) => {
|
|
21775
|
-
if (!isContainer(id)) return [id];
|
|
21776
|
-
const out = [];
|
|
21777
|
-
const visit = (nid) => {
|
|
21778
|
-
const kids = getChildren(nid);
|
|
21779
|
-
if (kids.length === 0) {
|
|
21780
|
-
if (!isContainer(nid)) out.push(nid);
|
|
21781
|
-
return;
|
|
21782
|
-
}
|
|
21783
|
-
for (const k of kids) visit(k);
|
|
21784
|
-
};
|
|
21785
|
-
visit(id);
|
|
21786
|
-
return out;
|
|
21787
|
-
};
|
|
21788
22442
|
return (id) => {
|
|
21789
22443
|
if (!isContainer(id)) {
|
|
21790
22444
|
const p = getPose(id);
|
|
21791
22445
|
return p === null ? null : getBounds(p);
|
|
21792
22446
|
}
|
|
21793
|
-
const leaves = leavesOf(id);
|
|
22447
|
+
const leaves = leavesOf(id, getChildren, isContainer);
|
|
21794
22448
|
if (leaves.length === 0) return null;
|
|
21795
22449
|
const leafBounds = [];
|
|
21796
22450
|
for (const leafId of leaves) {
|
|
@@ -22923,7 +23577,7 @@ function CanvasInner(props, ref) {
|
|
|
22923
23577
|
return {
|
|
22924
23578
|
worldX,
|
|
22925
23579
|
worldY,
|
|
22926
|
-
modifiers: m ? { alt: m.alt, shift: m.shift, meta: m.meta, ctrl: m.ctrl
|
|
23580
|
+
modifiers: m ? { alt: m.alt, shift: m.shift, meta: m.meta, ctrl: m.ctrl } : { alt: false, shift: false, meta: false, ctrl: false },
|
|
22927
23581
|
selection: effectiveSelectionRefForCtx.current,
|
|
22928
23582
|
adapter: effectiveAdapterRefForCtx.current,
|
|
22929
23583
|
applyOps: (ops, label) => {
|
|
@@ -26567,10 +27221,10 @@ function boundsOf(coords) {
|
|
|
26567
27221
|
}
|
|
26568
27222
|
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
26569
27223
|
}
|
|
26570
|
-
function useViewDepSource(currentViewRef, onViewChange, recenter, hostSize, animation) {
|
|
26571
|
-
const wiring = useRef({ currentViewRef, onViewChange, recenter, hostSize, animation });
|
|
26572
|
-
wiring.current = { currentViewRef, onViewChange, recenter, hostSize, animation };
|
|
26573
|
-
const shape = `${recenter ? "r" : ""}${hostSize ? "h" : ""}${animation ? "a" : ""}`;
|
|
27224
|
+
function useViewDepSource(currentViewRef, onViewChange, recenter, hostSize, animation, decay) {
|
|
27225
|
+
const wiring = useRef({ currentViewRef, onViewChange, recenter, hostSize, animation, decay });
|
|
27226
|
+
wiring.current = { currentViewRef, onViewChange, recenter, hostSize, animation, decay };
|
|
27227
|
+
const shape = `${recenter ? "r" : ""}${hostSize ? "h" : ""}${animation ? "a" : ""}${decay ? "d" : ""}`;
|
|
26574
27228
|
const shapeRef = useRef(null);
|
|
26575
27229
|
const viewApiRef = useRef(null);
|
|
26576
27230
|
if (viewApiRef.current === null || shapeRef.current !== shape) {
|
|
@@ -26589,6 +27243,10 @@ function useViewDepSource(currentViewRef, onViewChange, recenter, hostSize, anim
|
|
|
26589
27243
|
animate: (to, opts) => wiring.current.animation.animate(to, opts),
|
|
26590
27244
|
stopAnimation: () => wiring.current.animation.stop(),
|
|
26591
27245
|
animationTarget: () => wiring.current.animation.target()
|
|
27246
|
+
} : {},
|
|
27247
|
+
...decay ? {
|
|
27248
|
+
decay: (config) => wiring.current.decay.start(config),
|
|
27249
|
+
stopDecay: () => wiring.current.decay.cancel()
|
|
26592
27250
|
} : {}
|
|
26593
27251
|
};
|
|
26594
27252
|
}
|
|
@@ -27321,7 +27979,6 @@ function useActionsPropResolver(actions) {
|
|
|
27321
27979
|
}
|
|
27322
27980
|
if (!prop) return;
|
|
27323
27981
|
const unregisters = [];
|
|
27324
|
-
const restores = [];
|
|
27325
27982
|
const warnedIds = /* @__PURE__ */ new Set();
|
|
27326
27983
|
for (const [slotId, entry] of Object.entries(prop)) {
|
|
27327
27984
|
if (entry === null) {
|
|
@@ -27349,60 +28006,30 @@ function useActionsPropResolver(actions) {
|
|
|
27349
28006
|
}
|
|
27350
28007
|
const { id: _drop, ...rest } = entry;
|
|
27351
28008
|
const merged = { ...existing, ...rest };
|
|
27352
|
-
restores.push(() => {
|
|
27353
|
-
reg.register(existing);
|
|
27354
|
-
});
|
|
27355
28009
|
unregisters.push(reg.register(merged));
|
|
27356
28010
|
}
|
|
27357
28011
|
return () => {
|
|
27358
28012
|
for (const u of unregisters) u();
|
|
27359
|
-
for (const r of restores) r();
|
|
27360
28013
|
};
|
|
27361
28014
|
}, [reg, actions]);
|
|
27362
28015
|
}
|
|
27363
|
-
var viewportWheelPanAction = {
|
|
27364
|
-
id: "viewport.wheelPan",
|
|
27365
|
-
label: "Pan (wheel)",
|
|
27366
|
-
group: "viewport",
|
|
27367
|
-
/**
|
|
27368
|
-
* Plain wheel → pan; Shift+wheel → horizontal pan (axis swap).
|
|
27369
|
-
* Cmd+wheel is claimed by `viewportZoomAction`. The matcher's strict
|
|
27370
|
-
* modifier check keeps the bindings exclusive: omitting `mods` forbids
|
|
27371
|
-
* any modifier, and `mods: { shift: true }` forbids the others.
|
|
27372
|
-
*/
|
|
27373
|
-
defaultBinding: [
|
|
27374
|
-
{ spec: { kind: "wheel" }, opts: {} },
|
|
27375
|
-
{ spec: { kind: "wheel", mods: { shift: true } }, opts: { params: { swapAxis: true } } }
|
|
27376
|
-
],
|
|
27377
|
-
requires: ["view"],
|
|
27378
|
-
invoker: {
|
|
27379
|
-
timing: "immediate",
|
|
27380
|
-
run(deps, params) {
|
|
27381
|
-
const view = deps.view;
|
|
27382
|
-
if (!view) return;
|
|
27383
|
-
const deltaX = params?.deltaX ?? 0;
|
|
27384
|
-
const deltaY = params?.deltaY ?? 0;
|
|
27385
|
-
const current = view.get();
|
|
27386
|
-
const swap = params?.swapAxis === true;
|
|
27387
|
-
const dx = swap ? (deltaX !== 0 ? deltaX : deltaY) / current.scale.x : deltaX / current.scale.x;
|
|
27388
|
-
const dy = swap ? 0 : deltaY / current.scale.y;
|
|
27389
|
-
view.set({ ...current, x: current.x + dx, y: current.y + dy });
|
|
27390
|
-
}
|
|
27391
|
-
},
|
|
27392
|
-
enabled: () => true
|
|
27393
|
-
};
|
|
27394
28016
|
function useViewportActions(args) {
|
|
27395
28017
|
const { pan, zoom, pinchZoom } = args;
|
|
27396
28018
|
const reg = useActionsRegistry();
|
|
27397
28019
|
const regRef = useRef(reg);
|
|
27398
28020
|
regRef.current = reg;
|
|
28021
|
+
const panKey = typeof pan === "object" ? JSON.stringify(pan) : String(pan);
|
|
27399
28022
|
const zoomKey = typeof zoom === "object" ? JSON.stringify(zoom) : String(zoom);
|
|
27400
28023
|
const pinchKey = typeof pinchZoom === "object" ? JSON.stringify(pinchZoom) : String(pinchZoom);
|
|
27401
28024
|
useEffect(() => {
|
|
27402
28025
|
const r = regRef.current;
|
|
27403
28026
|
if (!r) return;
|
|
27404
28027
|
const unregisters = [];
|
|
27405
|
-
if (pan)
|
|
28028
|
+
if (pan) {
|
|
28029
|
+
unregisters.push(
|
|
28030
|
+
r.register(makeViewportWheelPanAction(typeof pan === "object" ? pan : {}))
|
|
28031
|
+
);
|
|
28032
|
+
}
|
|
27406
28033
|
if (zoom) {
|
|
27407
28034
|
const zoomAction = typeof zoom === "object" ? makeViewportZoomAction(zoom) : makeViewportZoomAction();
|
|
27408
28035
|
unregisters.push(r.register(zoomAction));
|
|
@@ -27417,7 +28044,7 @@ function useViewportActions(args) {
|
|
|
27417
28044
|
return () => {
|
|
27418
28045
|
for (const u of unregisters) u();
|
|
27419
28046
|
};
|
|
27420
|
-
}, [
|
|
28047
|
+
}, [panKey, zoomKey, pinchKey]);
|
|
27421
28048
|
}
|
|
27422
28049
|
function createNodeRouting() {
|
|
27423
28050
|
const entries = [];
|
|
@@ -27630,7 +28257,6 @@ function SceneCanvasInner(props, ref) {
|
|
|
27630
28257
|
() => isSerialized(sceneInput) ? sceneFromJSON(sceneInput, {}) : null
|
|
27631
28258
|
);
|
|
27632
28259
|
const scene = bakedScene ?? sceneInput;
|
|
27633
|
-
useSyncExternalStore(scene.subscribe, scene.getVersion, scene.getVersion);
|
|
27634
28260
|
const { view: viewProp, onViewChange: onViewChangeProp, defaultView, ...restProps } = rest;
|
|
27635
28261
|
const internalCanvasRef = useRef(null);
|
|
27636
28262
|
const canvasApiRef = useRef(null);
|
|
@@ -27661,6 +28287,9 @@ function SceneCanvasInner(props, ref) {
|
|
|
27661
28287
|
useEffect(() => scene.overrides.subscribe(() => {
|
|
27662
28288
|
canvasApiRef.current?.requestRedraw?.();
|
|
27663
28289
|
}), [scene]);
|
|
28290
|
+
useEffect(() => scene.subscribe(() => {
|
|
28291
|
+
canvasApiRef.current?.requestRedraw?.();
|
|
28292
|
+
}), [scene]);
|
|
27664
28293
|
const currentViewRef = useRef(
|
|
27665
28294
|
viewProp ?? defaultView ?? { x: 0, y: 0, scale: { x: 1, y: 1 } }
|
|
27666
28295
|
);
|
|
@@ -27841,13 +28470,13 @@ function SceneCanvasInner(props, ref) {
|
|
|
27841
28470
|
const viewportRegistered = !!viewport;
|
|
27842
28471
|
const inertiaEnabled = !!viewport?.inertia;
|
|
27843
28472
|
const inertiaObj = typeof viewport?.inertia === "object" ? viewport.inertia : void 0;
|
|
27844
|
-
const handToolInertia = inertiaEnabled
|
|
27845
|
-
friction: inertiaObj
|
|
27846
|
-
minSpeed: inertiaObj
|
|
27847
|
-
boundary: inertiaObj
|
|
27848
|
-
bounds: inertiaObj
|
|
28473
|
+
const handToolInertia = inertiaEnabled ? {
|
|
28474
|
+
friction: inertiaObj?.friction,
|
|
28475
|
+
minSpeed: inertiaObj?.minSpeed,
|
|
28476
|
+
boundary: inertiaObj?.boundary,
|
|
28477
|
+
bounds: inertiaObj?.bounds
|
|
27849
28478
|
} : void 0;
|
|
27850
|
-
const handTool = useHandTool(handToolInertia ? {} : {});
|
|
28479
|
+
const handTool = useHandTool(handToolInertia ? { inertia: handToolInertia } : {});
|
|
27851
28480
|
const viewportAmbient = [];
|
|
27852
28481
|
const baseRequestedTools = defaultTools ?? (toolBundle ? BUNDLE_TOOLS[toolBundle] : null) ?? (viewportRegistered ? ["select", "rotate", "hand"] : ["select", "rotate"]);
|
|
27853
28482
|
const KNOWN_BUILTIN_IDS = /* @__PURE__ */ new Set([
|
|
@@ -28300,7 +28929,7 @@ function SceneCanvasInner(props, ref) {
|
|
|
28300
28929
|
dispatcher,
|
|
28301
28930
|
getActionRef,
|
|
28302
28931
|
pickEvery: internalPickEvery,
|
|
28303
|
-
viewportPanEnabled: viewport?.pan
|
|
28932
|
+
viewportPanEnabled: viewport?.pan ?? true,
|
|
28304
28933
|
viewportZoom: resolvedViewportZoom,
|
|
28305
28934
|
viewportPinchZoom: viewport?.pinchZoom ?? true,
|
|
28306
28935
|
viewportRecenter: viewport?.recenter,
|
|
@@ -28591,6 +29220,7 @@ function StandardActionsRegistrar({
|
|
|
28591
29220
|
getActionRef.current = null;
|
|
28592
29221
|
};
|
|
28593
29222
|
}, [registry22, getActionRef]);
|
|
29223
|
+
const decayLoop = useDecayLoop();
|
|
28594
29224
|
const view = useViewDepSource(
|
|
28595
29225
|
currentViewRef,
|
|
28596
29226
|
onViewChange,
|
|
@@ -28599,7 +29229,8 @@ function StandardActionsRegistrar({
|
|
|
28599
29229
|
const el = canvasRef.current;
|
|
28600
29230
|
return el ? { width: el.clientWidth, height: el.clientHeight } : null;
|
|
28601
29231
|
},
|
|
28602
|
-
viewAnimation
|
|
29232
|
+
viewAnimation,
|
|
29233
|
+
decayLoop
|
|
28603
29234
|
);
|
|
28604
29235
|
const sceneAsHistory = scene;
|
|
28605
29236
|
useStandardActions({ selection, scene, view, history: sceneAsHistory });
|
|
@@ -29032,8 +29663,7 @@ function MinimapCanvasInner(props) {
|
|
|
29032
29663
|
}, [mainView, mainViewDims, indicatorStyle]);
|
|
29033
29664
|
const extraCommands = useMemo(() => [indicatorCmd], [indicatorCmd]);
|
|
29034
29665
|
const localCanvasRef = useRef(null);
|
|
29035
|
-
const
|
|
29036
|
-
const capturedPointerIdRef = useRef(null);
|
|
29666
|
+
const sessionRef = useRef(null);
|
|
29037
29667
|
const mainViewRef = useRef(mainView);
|
|
29038
29668
|
const mainViewDimsRef = useRef(mainViewDims);
|
|
29039
29669
|
const onMainViewChangeRef = useRef(onMainViewChange);
|
|
@@ -29062,36 +29692,18 @@ function MinimapCanvasInner(props) {
|
|
|
29062
29692
|
}, []);
|
|
29063
29693
|
const handlePointerDown = useCallback((ev) => {
|
|
29064
29694
|
const canvas = localCanvasRef.current;
|
|
29065
|
-
if (!canvas) return;
|
|
29695
|
+
if (!canvas || sessionRef.current) return;
|
|
29066
29696
|
if (ev.pointerType === "mouse" && ev.button !== 0) return;
|
|
29067
|
-
|
|
29068
|
-
|
|
29069
|
-
}
|
|
29070
|
-
|
|
29071
|
-
|
|
29072
|
-
|
|
29073
|
-
|
|
29074
|
-
|
|
29075
|
-
const handlePointerMove = useCallback((ev) => {
|
|
29076
|
-
if (!dragActiveRef.current) return;
|
|
29077
|
-
if (capturedPointerIdRef.current !== null && ev.pointerId !== capturedPointerIdRef.current) {
|
|
29078
|
-
return;
|
|
29079
|
-
}
|
|
29697
|
+
const done = () => {
|
|
29698
|
+
sessionRef.current = null;
|
|
29699
|
+
};
|
|
29700
|
+
sessionRef.current = openPointerSession(canvas, ev, {
|
|
29701
|
+
onMove: recenterFromPointer,
|
|
29702
|
+
onEnd: done,
|
|
29703
|
+
onCancel: done
|
|
29704
|
+
});
|
|
29080
29705
|
recenterFromPointer(ev);
|
|
29081
29706
|
}, [recenterFromPointer]);
|
|
29082
|
-
const releaseCapture = useCallback((ev) => {
|
|
29083
|
-
const canvas = localCanvasRef.current;
|
|
29084
|
-
if (canvas) {
|
|
29085
|
-
try {
|
|
29086
|
-
if (canvas.hasPointerCapture?.(ev.pointerId)) {
|
|
29087
|
-
canvas.releasePointerCapture(ev.pointerId);
|
|
29088
|
-
}
|
|
29089
|
-
} catch {
|
|
29090
|
-
}
|
|
29091
|
-
}
|
|
29092
|
-
dragActiveRef.current = false;
|
|
29093
|
-
capturedPointerIdRef.current = null;
|
|
29094
|
-
}, []);
|
|
29095
29707
|
const setCanvasRef = useCallback((el) => {
|
|
29096
29708
|
localCanvasRef.current = el;
|
|
29097
29709
|
if (typeof canvasRef === "function") {
|
|
@@ -29104,16 +29716,11 @@ function MinimapCanvasInner(props) {
|
|
|
29104
29716
|
const canvas = localCanvasRef.current;
|
|
29105
29717
|
if (!canvas) return;
|
|
29106
29718
|
canvas.addEventListener("pointerdown", handlePointerDown);
|
|
29107
|
-
canvas.addEventListener("pointermove", handlePointerMove);
|
|
29108
|
-
canvas.addEventListener("pointerup", releaseCapture);
|
|
29109
|
-
canvas.addEventListener("pointercancel", releaseCapture);
|
|
29110
29719
|
return () => {
|
|
29111
29720
|
canvas.removeEventListener("pointerdown", handlePointerDown);
|
|
29112
|
-
|
|
29113
|
-
canvas.removeEventListener("pointerup", releaseCapture);
|
|
29114
|
-
canvas.removeEventListener("pointercancel", releaseCapture);
|
|
29721
|
+
sessionRef.current?.cancel();
|
|
29115
29722
|
};
|
|
29116
|
-
}, [handlePointerDown
|
|
29723
|
+
}, [handlePointerDown]);
|
|
29117
29724
|
return /* @__PURE__ */ jsx(
|
|
29118
29725
|
SceneViewCanvas,
|
|
29119
29726
|
{
|
|
@@ -29385,6 +29992,6 @@ function oklchToOklab(L, C, h) {
|
|
|
29385
29992
|
return [L, C * Math.cos(h), C * Math.sin(h)];
|
|
29386
29993
|
}
|
|
29387
29994
|
|
|
29388
|
-
export { ArrowIcon, EllipseIcon, FALLBACK_FIT_VIEW, LineIcon, MinimapCanvas, PATH_C, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, PencilIcon, RectIcon, SCRIPT_METRICS, SceneCanvas, SceneViewCanvas, SelectIcon, TextIcon, UnknownIcon, WeaselProvider, asNodeId, boundsOfPath, buildSceneViewCommands, computeFitView, computeIndicatorCommand, createScene, eligibleContribution, ellipsePath, evaluateEnabled, getMarker, getPaintKind, isBuiltinToolPref, linePath, markerDrawCommands, oklabToSrgbU8, oklchToOklab, rectPath, renderSceneToCanvas, renderSceneToPixels, resolveStrokeWidth, rgbaToHex, sceneFromJSON, textCommand, tileGeometry, useActionsRegistry, useActiveToolContext, useOptionalDepRegistry, useVisibleRaf };
|
|
29389
|
-
//# sourceMappingURL=chunk-
|
|
29390
|
-
//# sourceMappingURL=chunk-
|
|
29995
|
+
export { ArrowIcon, EllipseIcon, FALLBACK_FIT_VIEW, LineIcon, MinimapCanvas, PATH_C, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, PencilIcon, RectIcon, SCRIPT_METRICS, SceneCanvas, SceneViewCanvas, SelectIcon, TextIcon, UnknownIcon, WeaselProvider, asNodeId, boundsOfPath, buildSceneViewCommands, computeFitView, computeIndicatorCommand, createScene, eligibleContribution, ellipsePath, evaluateEnabled, getMarker, getPaintKind, isBuiltinToolPref, linePath, markerDrawCommands, oklabToSrgbU8, oklchToOklab, openPointerSession, rectPath, renderSceneToCanvas, renderSceneToPixels, resolveStrokeWidth, rgbaToHex, sceneFromJSON, startThresholdDrag, textCommand, tileGeometry, useActionsRegistry, useActiveToolContext, useOptionalDepRegistry, useVisibleRaf };
|
|
29996
|
+
//# sourceMappingURL=chunk-54ZWZ5FQ.js.map
|
|
29997
|
+
//# sourceMappingURL=chunk-54ZWZ5FQ.js.map
|