@shopify/klint 0.3.0 → 0.4.0
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 +86 -62
- package/dist/{Klint-CsVzll4n.d.cts → Klint-DqYL-aGU.d.cts} +204 -332
- package/dist/{Klint-CsVzll4n.d.ts → Klint-DqYL-aGU.d.ts} +204 -332
- package/dist/index.cjs +872 -1184
- package/dist/index.d.cts +3 -29
- package/dist/index.d.ts +3 -29
- package/dist/index.js +868 -1184
- package/dist/plugins/index.cjs +606 -466
- package/dist/plugins/index.d.cts +440 -154
- package/dist/plugins/index.d.ts +440 -154
- package/dist/plugins/index.js +593 -466
- package/package.json +1 -1
- package/dist/chunk-3RG5ZIWI.js +0 -10
package/dist/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
__require
|
|
3
|
-
} from "./chunk-3RG5ZIWI.js";
|
|
4
|
-
|
|
5
1
|
// src/Klint.tsx
|
|
6
2
|
import React, { useRef, useEffect, useState, useCallback } from "react";
|
|
7
3
|
var DEFAULT_FPS = 60;
|
|
@@ -46,33 +42,23 @@ var CONFIG_PROPS = [
|
|
|
46
42
|
"__fillRule",
|
|
47
43
|
"__isPlaying"
|
|
48
44
|
];
|
|
49
|
-
function useAnimate(contextRef, draw, isVisible
|
|
45
|
+
function useAnimate(contextRef, draw, isVisible) {
|
|
50
46
|
const animationFrameId = useRef(0);
|
|
51
|
-
const frameTimeHistoryRef = useRef([]);
|
|
52
|
-
const frameStartTimeRef = useRef(0);
|
|
53
|
-
const frameCountRef = useRef(0);
|
|
54
|
-
const lastFpsUpdateRef = useRef(0);
|
|
55
|
-
const droppedFramesRef = useRef(0);
|
|
56
47
|
const animate = useCallback(
|
|
57
48
|
(timestamp = 0) => {
|
|
58
49
|
if (!contextRef.current || !isVisible) return;
|
|
59
50
|
if (!contextRef.current.__isReadyToDraw) return;
|
|
60
|
-
if (!contextRef.current.__isPlaying)
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
51
|
+
if (!contextRef.current.__isPlaying) return;
|
|
63
52
|
const context = contextRef.current;
|
|
64
53
|
const now = timestamp;
|
|
65
54
|
const target = 1e3 / context.fps;
|
|
66
55
|
if (!context.__lastTargetTime) {
|
|
67
56
|
context.__lastTargetTime = now;
|
|
68
57
|
context.__lastRealTime = now;
|
|
69
|
-
frameStartTimeRef.current = now;
|
|
70
|
-
lastFpsUpdateRef.current = now;
|
|
71
58
|
}
|
|
72
59
|
const sinceLast = now - context.__lastTargetTime;
|
|
73
60
|
const epsilon = 5;
|
|
74
61
|
if (sinceLast >= target - epsilon) {
|
|
75
|
-
const frameStart = enablePerformanceTracking && context.__performance ? performance.now() : 0;
|
|
76
62
|
context.deltaTime = now - context.__lastRealTime;
|
|
77
63
|
draw(context);
|
|
78
64
|
if (context.time > 1e7) context.time = 0;
|
|
@@ -81,40 +67,10 @@ function useAnimate(contextRef, draw, isVisible, enablePerformanceTracking = fal
|
|
|
81
67
|
context.frame++;
|
|
82
68
|
context.__lastTargetTime = now;
|
|
83
69
|
context.__lastRealTime = now;
|
|
84
|
-
if (enablePerformanceTracking && context.__performance) {
|
|
85
|
-
const frameTime = performance.now() - frameStart;
|
|
86
|
-
const targetFrameTime = 1e3 / context.fps;
|
|
87
|
-
frameTimeHistoryRef.current.push(frameTime);
|
|
88
|
-
if (frameTimeHistoryRef.current.length > 60) {
|
|
89
|
-
frameTimeHistoryRef.current.shift();
|
|
90
|
-
}
|
|
91
|
-
const avgFrameTime = frameTimeHistoryRef.current.reduce((a, b) => a + b, 0) / frameTimeHistoryRef.current.length;
|
|
92
|
-
context.__performance.frameTime = frameTime;
|
|
93
|
-
context.__performance.averageFrameTime = avgFrameTime;
|
|
94
|
-
context.__performance.minFrameTime = Math.min(
|
|
95
|
-
...frameTimeHistoryRef.current
|
|
96
|
-
);
|
|
97
|
-
context.__performance.maxFrameTime = Math.max(
|
|
98
|
-
...frameTimeHistoryRef.current
|
|
99
|
-
);
|
|
100
|
-
if (frameTime > targetFrameTime * 1.1) {
|
|
101
|
-
droppedFramesRef.current++;
|
|
102
|
-
}
|
|
103
|
-
context.__performance.droppedFrames = droppedFramesRef.current;
|
|
104
|
-
frameCountRef.current++;
|
|
105
|
-
if (now - lastFpsUpdateRef.current >= 1e3) {
|
|
106
|
-
context.__performance.fps = frameCountRef.current;
|
|
107
|
-
frameCountRef.current = 0;
|
|
108
|
-
lastFpsUpdateRef.current = now;
|
|
109
|
-
if (typeof performance !== "undefined" && performance.memory) {
|
|
110
|
-
context.__performance.memoryUsage = performance.memory.usedJSHeapSize / 1048576;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
70
|
}
|
|
115
71
|
animationFrameId.current = requestAnimationFrame(animate);
|
|
116
72
|
},
|
|
117
|
-
[draw, isVisible, contextRef
|
|
73
|
+
[draw, isVisible, contextRef]
|
|
118
74
|
);
|
|
119
75
|
return {
|
|
120
76
|
animate,
|
|
@@ -127,8 +83,7 @@ function Klint({
|
|
|
127
83
|
draw,
|
|
128
84
|
options = {},
|
|
129
85
|
preload,
|
|
130
|
-
onVisible
|
|
131
|
-
enablePerformanceTracking = false
|
|
86
|
+
onVisible
|
|
132
87
|
}) {
|
|
133
88
|
const canvasRef = useRef(null);
|
|
134
89
|
const containerRef = useRef(null);
|
|
@@ -139,21 +94,26 @@ function Klint({
|
|
|
139
94
|
);
|
|
140
95
|
const [isVisible, setIsVisible] = useState(true);
|
|
141
96
|
useEffect(() => {
|
|
97
|
+
const resetContext = () => {
|
|
98
|
+
if (contextRef.current) {
|
|
99
|
+
const ctx = contextRef.current;
|
|
100
|
+
ctx.__isPlaying = false;
|
|
101
|
+
ctx.frame = 0;
|
|
102
|
+
ctx.time = 0;
|
|
103
|
+
ctx.__offscreens?.clear();
|
|
104
|
+
ctx.__startedShape = false;
|
|
105
|
+
ctx.__currentShape = null;
|
|
106
|
+
ctx.__startedContour = false;
|
|
107
|
+
ctx.__currentContours = null;
|
|
108
|
+
ctx.__currentContour = null;
|
|
109
|
+
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
142
112
|
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
143
|
-
import.meta.hot.dispose(
|
|
144
|
-
console.log("[Klint] Component unmounting due to HMR");
|
|
145
|
-
if (contextRef.current) {
|
|
146
|
-
contextRef.current.__isPlaying = false;
|
|
147
|
-
}
|
|
148
|
-
});
|
|
113
|
+
import.meta.hot.dispose(resetContext);
|
|
149
114
|
}
|
|
150
115
|
if (typeof module !== "undefined" && module.hot) {
|
|
151
|
-
module.hot.dispose(
|
|
152
|
-
console.log("[Klint] Component unmounting due to Webpack HMR");
|
|
153
|
-
if (contextRef.current) {
|
|
154
|
-
contextRef.current.__isPlaying = false;
|
|
155
|
-
}
|
|
156
|
-
});
|
|
116
|
+
module.hot.dispose(resetContext);
|
|
157
117
|
}
|
|
158
118
|
}, []);
|
|
159
119
|
const __options = {
|
|
@@ -162,12 +122,7 @@ function Klint({
|
|
|
162
122
|
};
|
|
163
123
|
const [toStaticImage, setStaticImage] = useState(null);
|
|
164
124
|
const initContext = context?.initCoreContext;
|
|
165
|
-
const { animate, animationFrameId } = useAnimate(
|
|
166
|
-
contextRef,
|
|
167
|
-
draw,
|
|
168
|
-
isVisible,
|
|
169
|
-
enablePerformanceTracking
|
|
170
|
-
);
|
|
125
|
+
const { animate, animationFrameId } = useAnimate(contextRef, draw, isVisible);
|
|
171
126
|
const updateCanvasSize = (shouldRedraw = false) => {
|
|
172
127
|
if (!containerRef.current || !contextRef.current || !canvasRef.current)
|
|
173
128
|
return;
|
|
@@ -197,16 +152,6 @@ function Klint({
|
|
|
197
152
|
const context2 = contextRef.current;
|
|
198
153
|
if (!context2) return;
|
|
199
154
|
context2.__dpr = dpr;
|
|
200
|
-
if (enablePerformanceTracking) {
|
|
201
|
-
context2.__performance = {
|
|
202
|
-
fps: 0,
|
|
203
|
-
frameTime: 0,
|
|
204
|
-
averageFrameTime: 0,
|
|
205
|
-
minFrameTime: Infinity,
|
|
206
|
-
maxFrameTime: 0,
|
|
207
|
-
droppedFrames: 0
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
155
|
if (__options.fps && __options.fps !== context2.fps) {
|
|
211
156
|
context2.fps = __options.fps;
|
|
212
157
|
}
|
|
@@ -756,6 +701,58 @@ var Easing = class {
|
|
|
756
701
|
p = p < 0 ? 0 : p > 1 ? 1 : p;
|
|
757
702
|
return p * p * (3 - 2 * p);
|
|
758
703
|
};
|
|
704
|
+
/**
|
|
705
|
+
* Damped spring easing. Physically expressive oscillation.
|
|
706
|
+
* @param val - Progress value (0 to 1)
|
|
707
|
+
* @param tension - Spring tension (0 to 1, default 0.5). Higher = faster oscillation.
|
|
708
|
+
* @param friction - Spring friction (0 to 1, default 0.5). Higher = less damping (more bouncy).
|
|
709
|
+
*/
|
|
710
|
+
this.spring = (val, tension = 0.5, friction = 0.5) => {
|
|
711
|
+
const omega = tension * 40;
|
|
712
|
+
const zeta = 1 - friction;
|
|
713
|
+
if (zeta < 1) {
|
|
714
|
+
const omegaD = omega * Math.sqrt(1 - zeta * zeta);
|
|
715
|
+
return 1 - Math.exp(-zeta * omega * val) * (Math.cos(omegaD * val) + zeta * omega / omegaD * Math.sin(omegaD * val));
|
|
716
|
+
}
|
|
717
|
+
return 1 - (1 + omega * val) * Math.exp(-omega * val);
|
|
718
|
+
};
|
|
719
|
+
/**
|
|
720
|
+
* Staircase easing. Quantizes to N discrete steps.
|
|
721
|
+
* @param val - Progress value (0 to 1)
|
|
722
|
+
* @param n - Number of steps (default 4)
|
|
723
|
+
*/
|
|
724
|
+
this.steps = (val, n = 4) => {
|
|
725
|
+
if (n <= 0) return val;
|
|
726
|
+
return Math.floor(val * n) / n;
|
|
727
|
+
};
|
|
728
|
+
/**
|
|
729
|
+
* Frame-rate independent exponential smoothing.
|
|
730
|
+
* Use instead of naive `lerp(a, b, 0.1)` which breaks at different FPS.
|
|
731
|
+
* @param current - Current value
|
|
732
|
+
* @param target - Target value
|
|
733
|
+
* @param smoothing - Smoothing factor (higher = faster convergence)
|
|
734
|
+
* @param deltaTime - Time since last frame in seconds
|
|
735
|
+
*/
|
|
736
|
+
this.damp = (current, target, smoothing, deltaTime) => {
|
|
737
|
+
return current + (target - current) * (1 - Math.exp(-smoothing * deltaTime));
|
|
738
|
+
};
|
|
739
|
+
/**
|
|
740
|
+
* Quick rise then decay. Great for hit effects, flashes.
|
|
741
|
+
* @param val - Progress value (0 to 1)
|
|
742
|
+
* @param k - Sharpness (default 6). Higher = sharper peak.
|
|
743
|
+
*/
|
|
744
|
+
this.impulse = (val, k = 6) => {
|
|
745
|
+
const h = k * val;
|
|
746
|
+
return h * Math.exp(1 - h);
|
|
747
|
+
};
|
|
748
|
+
/**
|
|
749
|
+
* Symmetric arc. Useful for jumps, throw curves.
|
|
750
|
+
* @param val - Progress value (0 to 1)
|
|
751
|
+
* @param k - Steepness (default 1)
|
|
752
|
+
*/
|
|
753
|
+
this.parabola = (val, k = 1) => {
|
|
754
|
+
return Math.pow(4 * val * (1 - val), k);
|
|
755
|
+
};
|
|
759
756
|
this.log = () => {
|
|
760
757
|
console.log(this);
|
|
761
758
|
};
|
|
@@ -1209,17 +1206,6 @@ var Text = class {
|
|
|
1209
1206
|
};
|
|
1210
1207
|
var Text_default = Text;
|
|
1211
1208
|
|
|
1212
|
-
// src/elements/Thing.tsx
|
|
1213
|
-
var Thing = class {
|
|
1214
|
-
constructor(ctx) {
|
|
1215
|
-
this.context = ctx;
|
|
1216
|
-
}
|
|
1217
|
-
log() {
|
|
1218
|
-
console.log(this.context);
|
|
1219
|
-
}
|
|
1220
|
-
};
|
|
1221
|
-
var Thing_default = Thing;
|
|
1222
|
-
|
|
1223
1209
|
// src/elements/Grid.tsx
|
|
1224
1210
|
var Grid = class {
|
|
1225
1211
|
/**
|
|
@@ -1653,505 +1639,427 @@ var Strip = class {
|
|
|
1653
1639
|
var Strip_default = Strip;
|
|
1654
1640
|
|
|
1655
1641
|
// src/elements/Noise.tsx
|
|
1656
|
-
var
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
this.
|
|
1664
|
-
|
|
1665
|
-
[1, 1, 0],
|
|
1666
|
-
[-1, 1, 0],
|
|
1667
|
-
[1, -1, 0],
|
|
1668
|
-
[-1, -1, 0],
|
|
1669
|
-
[1, 0, 1],
|
|
1670
|
-
[-1, 0, 1],
|
|
1671
|
-
[1, 0, -1],
|
|
1672
|
-
[-1, 0, -1],
|
|
1673
|
-
[0, 1, 1],
|
|
1674
|
-
[0, -1, 1],
|
|
1675
|
-
[0, 1, -1],
|
|
1676
|
-
[0, -1, -1]
|
|
1677
|
-
];
|
|
1678
|
-
this.grad4 = [
|
|
1679
|
-
[0, 1, 1, 1],
|
|
1680
|
-
[0, 1, 1, -1],
|
|
1681
|
-
[0, 1, -1, 1],
|
|
1682
|
-
[0, 1, -1, -1],
|
|
1683
|
-
[0, -1, 1, 1],
|
|
1684
|
-
[0, -1, 1, -1],
|
|
1685
|
-
[0, -1, -1, 1],
|
|
1686
|
-
[0, -1, -1, -1],
|
|
1687
|
-
[1, 0, 1, 1],
|
|
1688
|
-
[1, 0, 1, -1],
|
|
1689
|
-
[1, 0, -1, 1],
|
|
1690
|
-
[1, 0, -1, -1],
|
|
1691
|
-
[-1, 0, 1, 1],
|
|
1692
|
-
[-1, 0, 1, -1],
|
|
1693
|
-
[-1, 0, -1, 1],
|
|
1694
|
-
[-1, 0, -1, -1],
|
|
1695
|
-
[1, 1, 0, 1],
|
|
1696
|
-
[1, 1, 0, -1],
|
|
1697
|
-
[1, -1, 0, 1],
|
|
1698
|
-
[1, -1, 0, -1],
|
|
1699
|
-
[-1, 1, 0, 1],
|
|
1700
|
-
[-1, 1, 0, -1],
|
|
1701
|
-
[-1, -1, 0, 1],
|
|
1702
|
-
[-1, -1, 0, -1],
|
|
1703
|
-
[1, 1, 1, 0],
|
|
1704
|
-
[1, 1, -1, 0],
|
|
1705
|
-
[1, -1, 1, 0],
|
|
1706
|
-
[1, -1, -1, 0],
|
|
1707
|
-
[-1, 1, 1, 0],
|
|
1708
|
-
[-1, 1, -1, 0],
|
|
1709
|
-
[-1, -1, 1, 0],
|
|
1710
|
-
[-1, -1, -1, 0]
|
|
1711
|
-
];
|
|
1712
|
-
this.currentSeed = Math.random();
|
|
1713
|
-
this.F2 = 0.5 * (Math.sqrt(3) - 1);
|
|
1714
|
-
this.G2 = (3 - Math.sqrt(3)) / 6;
|
|
1715
|
-
this.F3 = 1 / 3;
|
|
1716
|
-
this.G3 = 1 / 6;
|
|
1717
|
-
this.F4 = (Math.sqrt(5) - 1) / 4;
|
|
1718
|
-
this.G4 = (5 - Math.sqrt(5)) / 20;
|
|
1719
|
-
this.context = ctx;
|
|
1720
|
-
this.buildPermutationTable();
|
|
1642
|
+
var _Noise = class _Noise {
|
|
1643
|
+
constructor(_ctx) {
|
|
1644
|
+
this._seed = Math.random();
|
|
1645
|
+
this.p = new Uint8Array(512);
|
|
1646
|
+
this.buildPerm();
|
|
1647
|
+
}
|
|
1648
|
+
rng() {
|
|
1649
|
+
const x = Math.sin(this._seed++) * 1e4;
|
|
1650
|
+
return x - Math.floor(x);
|
|
1721
1651
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
let n = 256;
|
|
1731
|
-
while (n > 0) {
|
|
1732
|
-
const index = Math.floor(this.random() * n--);
|
|
1733
|
-
const temp = p[n];
|
|
1734
|
-
p[n] = p[index];
|
|
1735
|
-
p[index] = temp;
|
|
1736
|
-
}
|
|
1737
|
-
this.perm = [];
|
|
1738
|
-
this.permMod12 = [];
|
|
1739
|
-
for (let i = 0; i < 512; i++) {
|
|
1740
|
-
this.perm[i] = p[i & 255];
|
|
1741
|
-
this.permMod12[i] = this.perm[i] % 12;
|
|
1652
|
+
buildPerm() {
|
|
1653
|
+
const t = new Uint8Array(256);
|
|
1654
|
+
for (let i = 0; i < 256; i++) t[i] = i;
|
|
1655
|
+
for (let i = 255; i > 0; i--) {
|
|
1656
|
+
const j = this.rng() * (i + 1) | 0;
|
|
1657
|
+
const tmp = t[i];
|
|
1658
|
+
t[i] = t[j];
|
|
1659
|
+
t[j] = tmp;
|
|
1742
1660
|
}
|
|
1661
|
+
for (let i = 0; i < 512; i++) this.p[i] = t[i & 255];
|
|
1743
1662
|
}
|
|
1744
|
-
/**
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
const x = Math.sin(this.currentSeed++) * 1e4;
|
|
1749
|
-
return x - Math.floor(x);
|
|
1663
|
+
/** Set seed for reproducible noise */
|
|
1664
|
+
seed(s) {
|
|
1665
|
+
this._seed = s ?? Math.random() * 1e4;
|
|
1666
|
+
this.buildPerm();
|
|
1750
1667
|
}
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
* @param seed - Seed value for reproducible noise
|
|
1754
|
-
*/
|
|
1755
|
-
seed(seed) {
|
|
1756
|
-
this.currentSeed = seed !== void 0 ? seed : Math.random() * 1e4;
|
|
1757
|
-
this.buildPermutationTable();
|
|
1758
|
-
}
|
|
1759
|
-
/**
|
|
1760
|
-
* Fade function for Perlin noise
|
|
1761
|
-
*/
|
|
1762
|
-
fade(t) {
|
|
1668
|
+
// ---- Utilities ----
|
|
1669
|
+
static fade(t) {
|
|
1763
1670
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
|
1764
1671
|
}
|
|
1765
|
-
|
|
1766
|
-
* Linear interpolation
|
|
1767
|
-
*/
|
|
1768
|
-
lerp(t, a, b) {
|
|
1672
|
+
static lerp(t, a, b) {
|
|
1769
1673
|
return a + t * (b - a);
|
|
1770
1674
|
}
|
|
1675
|
+
/** Improved Perlin gradient — maps 4-bit hash to one of 12 gradient directions */
|
|
1676
|
+
static grad3(h, x, y, z) {
|
|
1677
|
+
h &= 15;
|
|
1678
|
+
const u = h < 8 ? x : y;
|
|
1679
|
+
const v = h < 4 ? y : h === 12 || h === 14 ? x : z;
|
|
1680
|
+
return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);
|
|
1681
|
+
}
|
|
1771
1682
|
perlin(x, y, z, w) {
|
|
1772
|
-
if (y === void 0)
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
v,
|
|
1828
|
-
this.lerp(u, grad3(aaa, xf, yf, zf), grad3(baa, xf - 1, yf, zf)),
|
|
1829
|
-
this.lerp(u, grad3(aba, xf, yf - 1, zf), grad3(bba, xf - 1, yf - 1, zf))
|
|
1683
|
+
if (y === void 0) return this.perlin1(x);
|
|
1684
|
+
if (z === void 0) return this.perlin2(x, y);
|
|
1685
|
+
if (w === void 0) return this.perlin3(x, y, z);
|
|
1686
|
+
return this.perlin4(x, y, z, w);
|
|
1687
|
+
}
|
|
1688
|
+
perlin1(x) {
|
|
1689
|
+
const p = this.p;
|
|
1690
|
+
const fx = Math.floor(x);
|
|
1691
|
+
const X = fx & 255;
|
|
1692
|
+
const xf = x - fx;
|
|
1693
|
+
const u = _Noise.fade(xf);
|
|
1694
|
+
const g = (h, d) => (h & 1) === 0 ? d : -d;
|
|
1695
|
+
return _Noise.lerp(u, g(p[X], xf), g(p[X + 1], xf - 1));
|
|
1696
|
+
}
|
|
1697
|
+
perlin2(x, y) {
|
|
1698
|
+
const { fade, lerp } = _Noise;
|
|
1699
|
+
const p = this.p;
|
|
1700
|
+
const fx = Math.floor(x), fy = Math.floor(y);
|
|
1701
|
+
const X = fx & 255, Y = fy & 255;
|
|
1702
|
+
const xf = x - fx, yf = y - fy;
|
|
1703
|
+
const u = fade(xf), v = fade(yf);
|
|
1704
|
+
const g = (h, x2, y2) => {
|
|
1705
|
+
const b = h & 3;
|
|
1706
|
+
return ((b & 1) === 0 ? x2 : -x2) + ((b & 2) === 0 ? y2 : -y2);
|
|
1707
|
+
};
|
|
1708
|
+
const aa = p[p[X] + Y], ab = p[p[X] + Y + 1];
|
|
1709
|
+
const ba = p[p[X + 1] + Y], bb = p[p[X + 1] + Y + 1];
|
|
1710
|
+
return lerp(
|
|
1711
|
+
v,
|
|
1712
|
+
lerp(u, g(aa, xf, yf), g(ba, xf - 1, yf)),
|
|
1713
|
+
lerp(u, g(ab, xf, yf - 1), g(bb, xf - 1, yf - 1))
|
|
1714
|
+
);
|
|
1715
|
+
}
|
|
1716
|
+
perlin3(x, y, z) {
|
|
1717
|
+
const { fade, lerp, grad3 } = _Noise;
|
|
1718
|
+
const p = this.p;
|
|
1719
|
+
const fx = Math.floor(x), fy = Math.floor(y), fz = Math.floor(z);
|
|
1720
|
+
const X = fx & 255, Y = fy & 255, Z = fz & 255;
|
|
1721
|
+
const xf = x - fx, yf = y - fy, zf = z - fz;
|
|
1722
|
+
const u = fade(xf), v = fade(yf), w = fade(zf);
|
|
1723
|
+
const A = p[X] + Y, B = p[X + 1] + Y;
|
|
1724
|
+
const AA = p[A] + Z, AB = p[A + 1] + Z, BA = p[B] + Z, BB = p[B + 1] + Z;
|
|
1725
|
+
return lerp(
|
|
1726
|
+
w,
|
|
1727
|
+
lerp(
|
|
1728
|
+
v,
|
|
1729
|
+
lerp(u, grad3(p[AA], xf, yf, zf), grad3(p[BA], xf - 1, yf, zf)),
|
|
1730
|
+
lerp(u, grad3(p[AB], xf, yf - 1, zf), grad3(p[BB], xf - 1, yf - 1, zf))
|
|
1731
|
+
),
|
|
1732
|
+
lerp(
|
|
1733
|
+
v,
|
|
1734
|
+
lerp(
|
|
1735
|
+
u,
|
|
1736
|
+
grad3(p[AA + 1], xf, yf, zf - 1),
|
|
1737
|
+
grad3(p[BA + 1], xf - 1, yf, zf - 1)
|
|
1830
1738
|
),
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1739
|
+
lerp(
|
|
1740
|
+
u,
|
|
1741
|
+
grad3(p[AB + 1], xf, yf - 1, zf - 1),
|
|
1742
|
+
grad3(p[BB + 1], xf - 1, yf - 1, zf - 1)
|
|
1835
1743
|
)
|
|
1836
|
-
)
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
}
|
|
1744
|
+
)
|
|
1745
|
+
);
|
|
1746
|
+
}
|
|
1747
|
+
perlin4(x, y, z, w) {
|
|
1748
|
+
const { fade, lerp } = _Noise;
|
|
1749
|
+
const p = this.p;
|
|
1750
|
+
const fx = Math.floor(x), fy = Math.floor(y), fz = Math.floor(z), fw = Math.floor(w);
|
|
1751
|
+
const X = fx & 255, Y = fy & 255, Z = fz & 255, W = fw & 255;
|
|
1752
|
+
const xf = x - fx, yf = y - fy, zf = z - fz, wf = w - fw;
|
|
1753
|
+
const fu = fade(xf), fv = fade(yf), fW = fade(zf), ft = fade(wf);
|
|
1754
|
+
const g = (h2, x2, y2, z2, w2) => {
|
|
1755
|
+
const b = h2 & 31;
|
|
1756
|
+
const u = b < 24 ? x2 : y2;
|
|
1757
|
+
const v = b < 16 ? y2 : z2;
|
|
1758
|
+
const t = b < 8 ? z2 : w2;
|
|
1759
|
+
return ((b & 1) === 0 ? u : -u) + ((b & 2) === 0 ? v : -v) + ((b & 4) === 0 ? t : -t);
|
|
1760
|
+
};
|
|
1761
|
+
const h = (dx, dy, dz, dw) => p[p[p[p[X + dx] + Y + dy] + Z + dz] + W + dw];
|
|
1762
|
+
return lerp(
|
|
1763
|
+
ft,
|
|
1764
|
+
lerp(
|
|
1765
|
+
fW,
|
|
1766
|
+
lerp(
|
|
1767
|
+
fv,
|
|
1768
|
+
lerp(
|
|
1769
|
+
fu,
|
|
1770
|
+
g(h(0, 0, 0, 0), xf, yf, zf, wf),
|
|
1771
|
+
g(h(1, 0, 0, 0), xf - 1, yf, zf, wf)
|
|
1772
|
+
),
|
|
1773
|
+
lerp(
|
|
1774
|
+
fu,
|
|
1775
|
+
g(h(0, 1, 0, 0), xf, yf - 1, zf, wf),
|
|
1776
|
+
g(h(1, 1, 0, 0), xf - 1, yf - 1, zf, wf)
|
|
1777
|
+
)
|
|
1778
|
+
),
|
|
1779
|
+
lerp(
|
|
1780
|
+
fv,
|
|
1781
|
+
lerp(
|
|
1782
|
+
fu,
|
|
1783
|
+
g(h(0, 0, 1, 0), xf, yf, zf - 1, wf),
|
|
1784
|
+
g(h(1, 0, 1, 0), xf - 1, yf, zf - 1, wf)
|
|
1785
|
+
),
|
|
1786
|
+
lerp(
|
|
1787
|
+
fu,
|
|
1788
|
+
g(h(0, 1, 1, 0), xf, yf - 1, zf - 1, wf),
|
|
1789
|
+
g(h(1, 1, 1, 0), xf - 1, yf - 1, zf - 1, wf)
|
|
1790
|
+
)
|
|
1791
|
+
)
|
|
1792
|
+
),
|
|
1793
|
+
lerp(
|
|
1794
|
+
fW,
|
|
1795
|
+
lerp(
|
|
1796
|
+
fv,
|
|
1797
|
+
lerp(
|
|
1798
|
+
fu,
|
|
1799
|
+
g(h(0, 0, 0, 1), xf, yf, zf, wf - 1),
|
|
1800
|
+
g(h(1, 0, 0, 1), xf - 1, yf, zf, wf - 1)
|
|
1801
|
+
),
|
|
1802
|
+
lerp(
|
|
1803
|
+
fu,
|
|
1804
|
+
g(h(0, 1, 0, 1), xf, yf - 1, zf, wf - 1),
|
|
1805
|
+
g(h(1, 1, 0, 1), xf - 1, yf - 1, zf, wf - 1)
|
|
1806
|
+
)
|
|
1807
|
+
),
|
|
1808
|
+
lerp(
|
|
1809
|
+
fv,
|
|
1810
|
+
lerp(
|
|
1811
|
+
fu,
|
|
1812
|
+
g(h(0, 0, 1, 1), xf, yf, zf - 1, wf - 1),
|
|
1813
|
+
g(h(1, 0, 1, 1), xf - 1, yf, zf - 1, wf - 1)
|
|
1814
|
+
),
|
|
1815
|
+
lerp(
|
|
1816
|
+
fu,
|
|
1817
|
+
g(h(0, 1, 1, 1), xf, yf - 1, zf - 1, wf - 1),
|
|
1818
|
+
g(h(1, 1, 1, 1), xf - 1, yf - 1, zf - 1, wf - 1)
|
|
1819
|
+
)
|
|
1820
|
+
)
|
|
1821
|
+
)
|
|
1822
|
+
);
|
|
1841
1823
|
}
|
|
1842
1824
|
simplex(x, y, z, w) {
|
|
1843
|
-
if (y === void 0)
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1825
|
+
if (y === void 0) return this.perlin1(x);
|
|
1826
|
+
if (z === void 0) return this.simplex2(x, y);
|
|
1827
|
+
if (w === void 0) return this.simplex3(x, y, z);
|
|
1828
|
+
return this.simplex4(x, y, z, w);
|
|
1829
|
+
}
|
|
1830
|
+
simplex2(x, y) {
|
|
1831
|
+
const { F2, G2, grad3 } = _Noise;
|
|
1832
|
+
const p = this.p;
|
|
1833
|
+
const s = (x + y) * F2;
|
|
1834
|
+
const i = Math.floor(x + s), j = Math.floor(y + s);
|
|
1835
|
+
const t = (i + j) * G2;
|
|
1836
|
+
const x0 = x - (i - t), y0 = y - (j - t);
|
|
1837
|
+
const i1 = x0 > y0 ? 1 : 0, j1 = x0 > y0 ? 0 : 1;
|
|
1838
|
+
const x1 = x0 - i1 + G2, y1 = y0 - j1 + G2;
|
|
1839
|
+
const x2 = x0 - 1 + 2 * G2, y2 = y0 - 1 + 2 * G2;
|
|
1840
|
+
const ii = i & 255, jj = j & 255;
|
|
1841
|
+
const gi0 = p[ii + p[jj]] % 12;
|
|
1842
|
+
const gi1 = p[ii + i1 + p[jj + j1]] % 12;
|
|
1843
|
+
const gi2 = p[ii + 1 + p[jj + 1]] % 12;
|
|
1844
|
+
let n0 = 0, n1 = 0, n2 = 0;
|
|
1845
|
+
let t0 = 0.5 - x0 * x0 - y0 * y0;
|
|
1846
|
+
if (t0 >= 0) {
|
|
1847
|
+
t0 *= t0;
|
|
1848
|
+
n0 = t0 * t0 * grad3(gi0, x0, y0, 0);
|
|
1849
|
+
}
|
|
1850
|
+
let t1 = 0.5 - x1 * x1 - y1 * y1;
|
|
1851
|
+
if (t1 >= 0) {
|
|
1852
|
+
t1 *= t1;
|
|
1853
|
+
n1 = t1 * t1 * grad3(gi1, x1, y1, 0);
|
|
1854
|
+
}
|
|
1855
|
+
let t2 = 0.5 - x2 * x2 - y2 * y2;
|
|
1856
|
+
if (t2 >= 0) {
|
|
1857
|
+
t2 *= t2;
|
|
1858
|
+
n2 = t2 * t2 * grad3(gi2, x2, y2, 0);
|
|
1859
|
+
}
|
|
1860
|
+
return 70 * (n0 + n1 + n2);
|
|
1861
|
+
}
|
|
1862
|
+
simplex3(x, y, z) {
|
|
1863
|
+
const { F3, G3, grad3 } = _Noise;
|
|
1864
|
+
const p = this.p;
|
|
1865
|
+
const s = (x + y + z) * F3;
|
|
1866
|
+
const i = Math.floor(x + s), j = Math.floor(y + s), k = Math.floor(z + s);
|
|
1867
|
+
const t = (i + j + k) * G3;
|
|
1868
|
+
const x0 = x - (i - t), y0 = y - (j - t), z0 = z - (k - t);
|
|
1869
|
+
let i1, j1, k1;
|
|
1870
|
+
let i2, j2, k2;
|
|
1871
|
+
if (x0 >= y0) {
|
|
1872
|
+
if (y0 >= z0) {
|
|
1873
|
+
i1 = 1;
|
|
1874
|
+
j1 = 0;
|
|
1875
|
+
k1 = 0;
|
|
1876
|
+
i2 = 1;
|
|
1877
|
+
j2 = 1;
|
|
1878
|
+
k2 = 0;
|
|
1879
|
+
} else if (x0 >= z0) {
|
|
1857
1880
|
i1 = 1;
|
|
1858
1881
|
j1 = 0;
|
|
1882
|
+
k1 = 0;
|
|
1883
|
+
i2 = 1;
|
|
1884
|
+
j2 = 0;
|
|
1885
|
+
k2 = 1;
|
|
1859
1886
|
} else {
|
|
1860
1887
|
i1 = 0;
|
|
1861
|
-
j1 =
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
const y2 = y0 - 1 + 2 * this.G2;
|
|
1867
|
-
const ii = i & 255;
|
|
1868
|
-
const jj = j & 255;
|
|
1869
|
-
const gi0 = this.permMod12[ii + this.perm[jj]];
|
|
1870
|
-
const gi1 = this.permMod12[ii + i1 + this.perm[jj + j1]];
|
|
1871
|
-
const gi2 = this.permMod12[ii + 1 + this.perm[jj + 1]];
|
|
1872
|
-
let t0 = 0.5 - x0 * x0 - y0 * y0;
|
|
1873
|
-
if (t0 < 0) {
|
|
1874
|
-
n0 = 0;
|
|
1875
|
-
} else {
|
|
1876
|
-
t0 *= t0;
|
|
1877
|
-
n0 = t0 * t0 * this.dot2(this.grad3[gi0], x0, y0);
|
|
1878
|
-
}
|
|
1879
|
-
let t1 = 0.5 - x1 * x1 - y1 * y1;
|
|
1880
|
-
if (t1 < 0) {
|
|
1881
|
-
n1 = 0;
|
|
1882
|
-
} else {
|
|
1883
|
-
t1 *= t1;
|
|
1884
|
-
n1 = t1 * t1 * this.dot2(this.grad3[gi1], x1, y1);
|
|
1885
|
-
}
|
|
1886
|
-
let t2 = 0.5 - x2 * x2 - y2 * y2;
|
|
1887
|
-
if (t2 < 0) {
|
|
1888
|
-
n2 = 0;
|
|
1889
|
-
} else {
|
|
1890
|
-
t2 *= t2;
|
|
1891
|
-
n2 = t2 * t2 * this.dot2(this.grad3[gi2], x2, y2);
|
|
1892
|
-
}
|
|
1893
|
-
return 70 * (n0 + n1 + n2);
|
|
1894
|
-
} else if (w === void 0) {
|
|
1895
|
-
let n0 = 0, n1 = 0, n2 = 0, n3 = 0;
|
|
1896
|
-
const s = (x + y + z) * this.F3;
|
|
1897
|
-
const i = Math.floor(x + s);
|
|
1898
|
-
const j = Math.floor(y + s);
|
|
1899
|
-
const k = Math.floor(z + s);
|
|
1900
|
-
const t = (i + j + k) * this.G3;
|
|
1901
|
-
const X0 = i - t;
|
|
1902
|
-
const Y0 = j - t;
|
|
1903
|
-
const Z0 = k - t;
|
|
1904
|
-
const x0 = x - X0;
|
|
1905
|
-
const y0 = y - Y0;
|
|
1906
|
-
const z0 = z - Z0;
|
|
1907
|
-
let i1, j1, k1;
|
|
1908
|
-
let i2, j2, k2;
|
|
1909
|
-
if (x0 >= y0) {
|
|
1910
|
-
if (y0 >= z0) {
|
|
1911
|
-
i1 = 1;
|
|
1912
|
-
j1 = 0;
|
|
1913
|
-
k1 = 0;
|
|
1914
|
-
i2 = 1;
|
|
1915
|
-
j2 = 1;
|
|
1916
|
-
k2 = 0;
|
|
1917
|
-
} else if (x0 >= z0) {
|
|
1918
|
-
i1 = 1;
|
|
1919
|
-
j1 = 0;
|
|
1920
|
-
k1 = 0;
|
|
1921
|
-
i2 = 1;
|
|
1922
|
-
j2 = 0;
|
|
1923
|
-
k2 = 1;
|
|
1924
|
-
} else {
|
|
1925
|
-
i1 = 0;
|
|
1926
|
-
j1 = 0;
|
|
1927
|
-
k1 = 1;
|
|
1928
|
-
i2 = 1;
|
|
1929
|
-
j2 = 0;
|
|
1930
|
-
k2 = 1;
|
|
1931
|
-
}
|
|
1932
|
-
} else {
|
|
1933
|
-
if (y0 < z0) {
|
|
1934
|
-
i1 = 0;
|
|
1935
|
-
j1 = 0;
|
|
1936
|
-
k1 = 1;
|
|
1937
|
-
i2 = 0;
|
|
1938
|
-
j2 = 1;
|
|
1939
|
-
k2 = 1;
|
|
1940
|
-
} else if (x0 < z0) {
|
|
1941
|
-
i1 = 0;
|
|
1942
|
-
j1 = 1;
|
|
1943
|
-
k1 = 0;
|
|
1944
|
-
i2 = 0;
|
|
1945
|
-
j2 = 1;
|
|
1946
|
-
k2 = 1;
|
|
1947
|
-
} else {
|
|
1948
|
-
i1 = 0;
|
|
1949
|
-
j1 = 1;
|
|
1950
|
-
k1 = 0;
|
|
1951
|
-
i2 = 1;
|
|
1952
|
-
j2 = 1;
|
|
1953
|
-
k2 = 0;
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1956
|
-
const x1 = x0 - i1 + this.G3;
|
|
1957
|
-
const y1 = y0 - j1 + this.G3;
|
|
1958
|
-
const z1 = z0 - k1 + this.G3;
|
|
1959
|
-
const x2 = x0 - i2 + 2 * this.G3;
|
|
1960
|
-
const y2 = y0 - j2 + 2 * this.G3;
|
|
1961
|
-
const z2 = z0 - k2 + 2 * this.G3;
|
|
1962
|
-
const x3 = x0 - 1 + 3 * this.G3;
|
|
1963
|
-
const y3 = y0 - 1 + 3 * this.G3;
|
|
1964
|
-
const z3 = z0 - 1 + 3 * this.G3;
|
|
1965
|
-
const ii = i & 255;
|
|
1966
|
-
const jj = j & 255;
|
|
1967
|
-
const kk = k & 255;
|
|
1968
|
-
const gi0 = this.permMod12[ii + this.perm[jj + this.perm[kk]]];
|
|
1969
|
-
const gi1 = this.permMod12[ii + i1 + this.perm[jj + j1 + this.perm[kk + k1]]];
|
|
1970
|
-
const gi2 = this.permMod12[ii + i2 + this.perm[jj + j2 + this.perm[kk + k2]]];
|
|
1971
|
-
const gi3 = this.permMod12[ii + 1 + this.perm[jj + 1 + this.perm[kk + 1]]];
|
|
1972
|
-
let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
|
|
1973
|
-
if (t0 < 0) {
|
|
1974
|
-
n0 = 0;
|
|
1975
|
-
} else {
|
|
1976
|
-
t0 *= t0;
|
|
1977
|
-
n0 = t0 * t0 * this.dot3(this.grad3[gi0], x0, y0, z0);
|
|
1978
|
-
}
|
|
1979
|
-
let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
|
|
1980
|
-
if (t1 < 0) {
|
|
1981
|
-
n1 = 0;
|
|
1982
|
-
} else {
|
|
1983
|
-
t1 *= t1;
|
|
1984
|
-
n1 = t1 * t1 * this.dot3(this.grad3[gi1], x1, y1, z1);
|
|
1888
|
+
j1 = 0;
|
|
1889
|
+
k1 = 1;
|
|
1890
|
+
i2 = 1;
|
|
1891
|
+
j2 = 0;
|
|
1892
|
+
k2 = 1;
|
|
1985
1893
|
}
|
|
1986
|
-
|
|
1987
|
-
if (
|
|
1988
|
-
|
|
1894
|
+
} else {
|
|
1895
|
+
if (y0 < z0) {
|
|
1896
|
+
i1 = 0;
|
|
1897
|
+
j1 = 0;
|
|
1898
|
+
k1 = 1;
|
|
1899
|
+
i2 = 0;
|
|
1900
|
+
j2 = 1;
|
|
1901
|
+
k2 = 1;
|
|
1902
|
+
} else if (x0 < z0) {
|
|
1903
|
+
i1 = 0;
|
|
1904
|
+
j1 = 1;
|
|
1905
|
+
k1 = 0;
|
|
1906
|
+
i2 = 0;
|
|
1907
|
+
j2 = 1;
|
|
1908
|
+
k2 = 1;
|
|
1989
1909
|
} else {
|
|
1990
|
-
|
|
1991
|
-
|
|
1910
|
+
i1 = 0;
|
|
1911
|
+
j1 = 1;
|
|
1912
|
+
k1 = 0;
|
|
1913
|
+
i2 = 1;
|
|
1914
|
+
j2 = 1;
|
|
1915
|
+
k2 = 0;
|
|
1992
1916
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1917
|
+
}
|
|
1918
|
+
const x1 = x0 - i1 + G3, y1 = y0 - j1 + G3, z1 = z0 - k1 + G3;
|
|
1919
|
+
const x2 = x0 - i2 + 2 * G3, y2 = y0 - j2 + 2 * G3, z2 = z0 - k2 + 2 * G3;
|
|
1920
|
+
const x3 = x0 - 1 + 3 * G3, y3 = y0 - 1 + 3 * G3, z3 = z0 - 1 + 3 * G3;
|
|
1921
|
+
const ii = i & 255, jj = j & 255, kk = k & 255;
|
|
1922
|
+
const gi0 = p[ii + p[jj + p[kk]]] % 12;
|
|
1923
|
+
const gi1 = p[ii + i1 + p[jj + j1 + p[kk + k1]]] % 12;
|
|
1924
|
+
const gi2 = p[ii + i2 + p[jj + j2 + p[kk + k2]]] % 12;
|
|
1925
|
+
const gi3 = p[ii + 1 + p[jj + 1 + p[kk + 1]]] % 12;
|
|
1926
|
+
let n = 0;
|
|
1927
|
+
let tc = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
|
|
1928
|
+
if (tc >= 0) {
|
|
1929
|
+
tc *= tc;
|
|
1930
|
+
n += tc * tc * grad3(gi0, x0, y0, z0);
|
|
1931
|
+
}
|
|
1932
|
+
tc = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
|
|
1933
|
+
if (tc >= 0) {
|
|
1934
|
+
tc *= tc;
|
|
1935
|
+
n += tc * tc * grad3(gi1, x1, y1, z1);
|
|
1936
|
+
}
|
|
1937
|
+
tc = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
|
|
1938
|
+
if (tc >= 0) {
|
|
1939
|
+
tc *= tc;
|
|
1940
|
+
n += tc * tc * grad3(gi2, x2, y2, z2);
|
|
1941
|
+
}
|
|
1942
|
+
tc = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
|
|
1943
|
+
if (tc >= 0) {
|
|
1944
|
+
tc *= tc;
|
|
1945
|
+
n += tc * tc * grad3(gi3, x3, y3, z3);
|
|
1946
|
+
}
|
|
1947
|
+
return 32 * n;
|
|
1948
|
+
}
|
|
1949
|
+
simplex4(x, y, z, w) {
|
|
1950
|
+
const { F4, G4 } = _Noise;
|
|
1951
|
+
const p = this.p;
|
|
1952
|
+
const s = (x + y + z + w) * F4;
|
|
1953
|
+
const i = Math.floor(x + s), j = Math.floor(y + s), k = Math.floor(z + s), l = Math.floor(w + s);
|
|
1954
|
+
const t = (i + j + k + l) * G4;
|
|
1955
|
+
const x0 = x - (i - t), y0 = y - (j - t), z0 = z - (k - t), w0 = w - (l - t);
|
|
1956
|
+
let rx = 0, ry = 0, rz = 0, rw = 0;
|
|
1957
|
+
if (x0 > y0) rx++;
|
|
1958
|
+
else ry++;
|
|
1959
|
+
if (x0 > z0) rx++;
|
|
1960
|
+
else rz++;
|
|
1961
|
+
if (x0 > w0) rx++;
|
|
1962
|
+
else rw++;
|
|
1963
|
+
if (y0 > z0) ry++;
|
|
1964
|
+
else rz++;
|
|
1965
|
+
if (y0 > w0) ry++;
|
|
1966
|
+
else rw++;
|
|
1967
|
+
if (z0 > w0) rz++;
|
|
1968
|
+
else rw++;
|
|
1969
|
+
const i1 = +(rx >= 3), j1 = +(ry >= 3), k1 = +(rz >= 3), l1 = +(rw >= 3);
|
|
1970
|
+
const i2 = +(rx >= 2), j2 = +(ry >= 2), k2 = +(rz >= 2), l2 = +(rw >= 2);
|
|
1971
|
+
const i3 = +(rx >= 1), j3 = +(ry >= 1), k3 = +(rz >= 1), l3 = +(rw >= 1);
|
|
1972
|
+
const x1 = x0 - i1 + G4, y1 = y0 - j1 + G4, z1 = z0 - k1 + G4, w1 = w0 - l1 + G4;
|
|
1973
|
+
const x2 = x0 - i2 + 2 * G4, y2 = y0 - j2 + 2 * G4, z2 = z0 - k2 + 2 * G4, w2 = w0 - l2 + 2 * G4;
|
|
1974
|
+
const x3 = x0 - i3 + 3 * G4, y3 = y0 - j3 + 3 * G4, z3 = z0 - k3 + 3 * G4, w3 = w0 - l3 + 3 * G4;
|
|
1975
|
+
const x4 = x0 - 1 + 4 * G4, y4 = y0 - 1 + 4 * G4, z4 = z0 - 1 + 4 * G4, w4 = w0 - 1 + 4 * G4;
|
|
1976
|
+
const ii = i & 255, jj = j & 255, kk = k & 255, ll = l & 255;
|
|
1977
|
+
const g4 = (gi, x5, y5, z5, w5) => {
|
|
1978
|
+
const g = gi >> 3;
|
|
1979
|
+
const b = gi & 7;
|
|
1980
|
+
let a, c, d;
|
|
1981
|
+
if (g === 0) {
|
|
1982
|
+
a = y5;
|
|
1983
|
+
c = z5;
|
|
1984
|
+
d = w5;
|
|
1985
|
+
} else if (g === 1) {
|
|
1986
|
+
a = x5;
|
|
1987
|
+
c = z5;
|
|
1988
|
+
d = w5;
|
|
1989
|
+
} else if (g === 2) {
|
|
1990
|
+
a = x5;
|
|
1991
|
+
c = y5;
|
|
1992
|
+
d = w5;
|
|
1996
1993
|
} else {
|
|
1997
|
-
|
|
1998
|
-
|
|
1994
|
+
a = x5;
|
|
1995
|
+
c = y5;
|
|
1996
|
+
d = z5;
|
|
1999
1997
|
}
|
|
2000
|
-
return
|
|
2001
|
-
}
|
|
2002
|
-
|
|
1998
|
+
return (b & 4 ? -a : a) + (b & 2 ? -c : c) + (b & 1 ? -d : d);
|
|
1999
|
+
};
|
|
2000
|
+
const gi0 = p[ii + p[jj + p[kk + p[ll]]]] & 31;
|
|
2001
|
+
const gi1 = p[ii + i1 + p[jj + j1 + p[kk + k1 + p[ll + l1]]]] & 31;
|
|
2002
|
+
const gi2 = p[ii + i2 + p[jj + j2 + p[kk + k2 + p[ll + l2]]]] & 31;
|
|
2003
|
+
const gi3 = p[ii + i3 + p[jj + j3 + p[kk + k3 + p[ll + l3]]]] & 31;
|
|
2004
|
+
const gi4 = p[ii + 1 + p[jj + 1 + p[kk + 1 + p[ll + 1]]]] & 31;
|
|
2005
|
+
let n = 0;
|
|
2006
|
+
let tc = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
|
|
2007
|
+
if (tc >= 0) {
|
|
2008
|
+
tc *= tc;
|
|
2009
|
+
n += tc * tc * g4(gi0, x0, y0, z0, w0);
|
|
2003
2010
|
}
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2011
|
+
tc = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
|
|
2012
|
+
if (tc >= 0) {
|
|
2013
|
+
tc *= tc;
|
|
2014
|
+
n += tc * tc * g4(gi1, x1, y1, z1, w1);
|
|
2015
|
+
}
|
|
2016
|
+
tc = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
|
|
2017
|
+
if (tc >= 0) {
|
|
2018
|
+
tc *= tc;
|
|
2019
|
+
n += tc * tc * g4(gi2, x2, y2, z2, w2);
|
|
2020
|
+
}
|
|
2021
|
+
tc = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
|
|
2022
|
+
if (tc >= 0) {
|
|
2023
|
+
tc *= tc;
|
|
2024
|
+
n += tc * tc * g4(gi3, x3, y3, z3, w3);
|
|
2025
|
+
}
|
|
2026
|
+
tc = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
|
|
2027
|
+
if (tc >= 0) {
|
|
2028
|
+
tc *= tc;
|
|
2029
|
+
n += tc * tc * g4(gi4, x4, y4, z4, w4);
|
|
2030
|
+
}
|
|
2031
|
+
return 27 * n;
|
|
2016
2032
|
}
|
|
2017
2033
|
hash(x, y, z, w) {
|
|
2018
|
-
let n
|
|
2034
|
+
let n;
|
|
2019
2035
|
if (y === void 0) {
|
|
2020
|
-
n = Math.sin(x * 12.9898 + this.
|
|
2036
|
+
n = Math.sin(x * 12.9898 + this._seed) * 43758.5453;
|
|
2021
2037
|
} else if (z === void 0) {
|
|
2022
|
-
n = Math.sin(x * 12.9898 + y * 78.233 + this.
|
|
2038
|
+
n = Math.sin(x * 12.9898 + y * 78.233 + this._seed) * 43758.5453;
|
|
2023
2039
|
} else if (w === void 0) {
|
|
2024
|
-
n = Math.sin(x * 12.9898 + y * 78.233 + z * 37.719 + this.
|
|
2040
|
+
n = Math.sin(x * 12.9898 + y * 78.233 + z * 37.719 + this._seed) * 43758.5453;
|
|
2025
2041
|
} else {
|
|
2026
|
-
n = Math.sin(
|
|
2042
|
+
n = Math.sin(
|
|
2043
|
+
x * 12.9898 + y * 78.233 + z * 37.719 + w * 53.137 + this._seed
|
|
2044
|
+
) * 43758.5453;
|
|
2027
2045
|
}
|
|
2028
2046
|
return n - Math.floor(n);
|
|
2029
2047
|
}
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
let zVal = void 0;
|
|
2037
|
-
let opts = typeof y === "object" ? y : typeof z === "object" ? z : {};
|
|
2038
|
-
if (typeof y === "number") yVal = y;
|
|
2039
|
-
if (typeof z === "number") zVal = z;
|
|
2040
|
-
if (options) opts = { ...opts, ...options };
|
|
2041
|
-
const octaves = opts.octaves ?? 4;
|
|
2042
|
-
if (octaves <= 0) return 0;
|
|
2043
|
-
let amplitude = opts.amplitude ?? 1;
|
|
2044
|
-
let frequency = opts.frequency ?? 1;
|
|
2045
|
-
const lacunarity = opts.lacunarity ?? 2;
|
|
2046
|
-
const gain = opts.gain ?? 0.5;
|
|
2047
|
-
let value = 0;
|
|
2048
|
-
let maxValue = 0;
|
|
2049
|
-
for (let i = 0; i < octaves; i++) {
|
|
2050
|
-
if (yVal === void 0) {
|
|
2051
|
-
value += amplitude * this.perlin(x * frequency);
|
|
2052
|
-
} else if (zVal === void 0) {
|
|
2053
|
-
value += amplitude * this.perlin(x * frequency, yVal * frequency);
|
|
2054
|
-
} else {
|
|
2055
|
-
value += amplitude * this.perlin(x * frequency, yVal * frequency, zVal * frequency);
|
|
2056
|
-
}
|
|
2057
|
-
maxValue += amplitude;
|
|
2058
|
-
amplitude *= gain;
|
|
2059
|
-
frequency *= lacunarity;
|
|
2060
|
-
}
|
|
2061
|
-
return maxValue === 0 ? 0 : value / maxValue;
|
|
2062
|
-
}
|
|
2063
|
-
/**
|
|
2064
|
-
* Turbulence noise (absolute value of noise)
|
|
2065
|
-
* Supports options object for octaves.
|
|
2066
|
-
*/
|
|
2067
|
-
turbulence(x, y, z, options) {
|
|
2068
|
-
let yVal = void 0;
|
|
2069
|
-
let zVal = void 0;
|
|
2070
|
-
let opts = typeof y === "object" ? y : typeof z === "object" ? z : {};
|
|
2071
|
-
if (typeof y === "number") yVal = y;
|
|
2072
|
-
if (typeof z === "number") zVal = z;
|
|
2073
|
-
if (options) opts = { ...opts, ...options };
|
|
2074
|
-
const octaves = opts.octaves ?? 4;
|
|
2075
|
-
if (octaves <= 0) return 0;
|
|
2076
|
-
let value = 0;
|
|
2077
|
-
let amplitude = 1;
|
|
2078
|
-
let frequency = 1;
|
|
2079
|
-
let maxValue = 0;
|
|
2080
|
-
for (let i = 0; i < octaves; i++) {
|
|
2081
|
-
let noise = 0;
|
|
2082
|
-
if (yVal === void 0) {
|
|
2083
|
-
noise = this.perlin(x * frequency);
|
|
2084
|
-
} else if (zVal === void 0) {
|
|
2085
|
-
noise = this.perlin(x * frequency, yVal * frequency);
|
|
2086
|
-
} else {
|
|
2087
|
-
noise = this.perlin(x * frequency, yVal * frequency, zVal * frequency);
|
|
2088
|
-
}
|
|
2089
|
-
value += amplitude * Math.abs(noise);
|
|
2090
|
-
maxValue += amplitude;
|
|
2091
|
-
amplitude *= 0.5;
|
|
2092
|
-
frequency *= 2;
|
|
2093
|
-
}
|
|
2094
|
-
return maxValue === 0 ? 0 : value / maxValue;
|
|
2095
|
-
}
|
|
2096
|
-
/**
|
|
2097
|
-
* Ridged multifractal noise (simple implementation)
|
|
2098
|
-
*/
|
|
2099
|
-
ridge(x, y, options) {
|
|
2100
|
-
let yVal = void 0;
|
|
2101
|
-
let opts = typeof y === "object" ? y : {};
|
|
2102
|
-
if (typeof y === "number") yVal = y;
|
|
2103
|
-
if (options) opts = { ...opts, ...options };
|
|
2104
|
-
const octaves = opts.octaves ?? 4;
|
|
2105
|
-
if (octaves <= 0) return 0;
|
|
2106
|
-
let amplitude = opts.amplitude ?? 1;
|
|
2107
|
-
let frequency = opts.frequency ?? 1;
|
|
2108
|
-
const lacunarity = opts.lacunarity ?? 2;
|
|
2109
|
-
const gain = opts.gain ?? 0.5;
|
|
2110
|
-
let value = 0;
|
|
2111
|
-
let weight = 1;
|
|
2112
|
-
let maxValue = 0;
|
|
2113
|
-
for (let i = 0; i < octaves; i++) {
|
|
2114
|
-
const n = yVal === void 0 ? this.perlin(x * frequency) : this.perlin(x * frequency, yVal * frequency);
|
|
2115
|
-
let signal = 1 - Math.abs(n);
|
|
2116
|
-
signal *= signal;
|
|
2117
|
-
signal *= weight;
|
|
2118
|
-
weight = signal * 2;
|
|
2119
|
-
weight = Math.min(Math.max(weight, 0), 1);
|
|
2120
|
-
value += signal * amplitude;
|
|
2121
|
-
maxValue += amplitude;
|
|
2122
|
-
amplitude *= gain;
|
|
2123
|
-
frequency *= lacunarity;
|
|
2124
|
-
}
|
|
2125
|
-
return maxValue === 0 ? 0 : value / maxValue;
|
|
2126
|
-
}
|
|
2127
|
-
/**
|
|
2128
|
-
* Cellular / Worley noise (2D simple implementation)
|
|
2129
|
-
*/
|
|
2130
|
-
cellular(x, y, options) {
|
|
2131
|
-
let yVal = void 0;
|
|
2132
|
-
let opts = typeof y === "object" ? y : {};
|
|
2133
|
-
if (typeof y === "number") yVal = y;
|
|
2134
|
-
if (options) opts = { ...opts, ...options };
|
|
2135
|
-
if (yVal === void 0) yVal = 0;
|
|
2136
|
-
const xi = Math.floor(x);
|
|
2137
|
-
const yi = Math.floor(yVal);
|
|
2138
|
-
const distance = opts.distance ?? "euclidean";
|
|
2139
|
-
let minDist = Infinity;
|
|
2140
|
-
for (let j = -1; j <= 1; j++) {
|
|
2141
|
-
for (let i = -1; i <= 1; i++) {
|
|
2142
|
-
const fx = i + this.hash(xi + i, yi + j);
|
|
2143
|
-
const fy = j + this.hash(yi + j, xi + i);
|
|
2144
|
-
const dx = fx + xi - x;
|
|
2145
|
-
const dy = fy + yi - yVal;
|
|
2146
|
-
const dist = distance === "manhattan" ? Math.abs(dx) + Math.abs(dy) : Math.sqrt(dx * dx + dy * dy);
|
|
2147
|
-
if (dist < minDist) minDist = dist;
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2150
|
-
const maxDist = Math.SQRT2;
|
|
2151
|
-
const normalized = 1 - Math.min(minDist / maxDist, 1);
|
|
2152
|
-
return normalized;
|
|
2048
|
+
// ---- GAUSSIAN RANDOM ----
|
|
2049
|
+
/** Box-Muller transform — returns normally distributed random number (seeded) */
|
|
2050
|
+
gaussianRandom(mean = 0, stddev = 1) {
|
|
2051
|
+
const u1 = 1 - this.rng();
|
|
2052
|
+
const u2 = this.rng();
|
|
2053
|
+
return mean + stddev * Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
|
|
2153
2054
|
}
|
|
2154
2055
|
};
|
|
2056
|
+
_Noise.F2 = (Math.sqrt(3) - 1) / 2;
|
|
2057
|
+
_Noise.G2 = (3 - Math.sqrt(3)) / 6;
|
|
2058
|
+
_Noise.F3 = 1 / 3;
|
|
2059
|
+
_Noise.G3 = 1 / 6;
|
|
2060
|
+
_Noise.F4 = (Math.sqrt(5) - 1) / 4;
|
|
2061
|
+
_Noise.G4 = (5 - Math.sqrt(5)) / 20;
|
|
2062
|
+
var Noise = _Noise;
|
|
2155
2063
|
var Noise_default = Noise;
|
|
2156
2064
|
|
|
2157
2065
|
// src/elements/Hotspot.tsx
|
|
@@ -2248,349 +2156,385 @@ var Hotspot = class {
|
|
|
2248
2156
|
};
|
|
2249
2157
|
var Hotspot_default = Hotspot;
|
|
2250
2158
|
|
|
2251
|
-
// src/elements/
|
|
2252
|
-
var
|
|
2253
|
-
constructor(
|
|
2254
|
-
this.
|
|
2255
|
-
this.
|
|
2256
|
-
this.
|
|
2257
|
-
this.
|
|
2159
|
+
// src/elements/Quadtree.tsx
|
|
2160
|
+
var Rectangle = class {
|
|
2161
|
+
constructor(x, y, w, h) {
|
|
2162
|
+
this.x = x;
|
|
2163
|
+
this.y = y;
|
|
2164
|
+
this.w = w;
|
|
2165
|
+
this.h = h;
|
|
2258
2166
|
}
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
*/
|
|
2262
|
-
batchDraw(drawFn) {
|
|
2263
|
-
this.context.save();
|
|
2264
|
-
this.context.beginPath();
|
|
2265
|
-
try {
|
|
2266
|
-
drawFn();
|
|
2267
|
-
} finally {
|
|
2268
|
-
this.context.restore();
|
|
2269
|
-
}
|
|
2167
|
+
contains(point) {
|
|
2168
|
+
return point.x >= this.x - this.w && point.x < this.x + this.w && point.y >= this.y - this.h && point.y < this.y + this.h;
|
|
2270
2169
|
}
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
*/
|
|
2274
|
-
useOffscreenCache(id, width, height, renderFn) {
|
|
2275
|
-
let offscreen = this.context.__offscreens.get(id);
|
|
2276
|
-
if (!offscreen || offscreen instanceof HTMLImageElement) {
|
|
2277
|
-
offscreen = this.context.createOffscreen(id, width, height);
|
|
2278
|
-
if (offscreen && !(offscreen instanceof HTMLImageElement)) {
|
|
2279
|
-
renderFn(offscreen);
|
|
2280
|
-
}
|
|
2281
|
-
}
|
|
2282
|
-
if (offscreen) {
|
|
2283
|
-
if (offscreen instanceof HTMLImageElement) {
|
|
2284
|
-
this.context.image(offscreen, 0, 0);
|
|
2285
|
-
} else {
|
|
2286
|
-
this.context.image(offscreen.canvas, 0, 0);
|
|
2287
|
-
}
|
|
2288
|
-
}
|
|
2170
|
+
intersects(range) {
|
|
2171
|
+
return !(range.x - range.w > this.x + this.w || range.x + range.w < this.x - this.w || range.y - range.h > this.y + this.h || range.y + range.h < this.y - this.h);
|
|
2289
2172
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
if (!cached || this.context.frame % interval === 0) {
|
|
2297
|
-
const result = fn();
|
|
2298
|
-
this.context[cacheKey] = { value: result, frame: this.context.frame };
|
|
2299
|
-
return result;
|
|
2300
|
-
}
|
|
2301
|
-
return cached.value;
|
|
2173
|
+
intersectsCircle(cx, cy, r) {
|
|
2174
|
+
const dx = Math.abs(cx - this.x);
|
|
2175
|
+
const dy = Math.abs(cy - this.y);
|
|
2176
|
+
if (dx > this.w + r || dy > this.h + r) return false;
|
|
2177
|
+
if (dx <= this.w || dy <= this.h) return true;
|
|
2178
|
+
return (dx - this.w) ** 2 + (dy - this.h) ** 2 <= r * r;
|
|
2302
2179
|
}
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
}
|
|
2330
|
-
};
|
|
2180
|
+
};
|
|
2181
|
+
var Quadtree = class _Quadtree {
|
|
2182
|
+
constructor(boundary, capacity = 4, maxDepth = 8, depth = 0) {
|
|
2183
|
+
this.ne = null;
|
|
2184
|
+
this.nw = null;
|
|
2185
|
+
this.se = null;
|
|
2186
|
+
this.sw = null;
|
|
2187
|
+
this.boundary = boundary;
|
|
2188
|
+
this.capacity = capacity;
|
|
2189
|
+
this.maxDepth = maxDepth;
|
|
2190
|
+
this.depth = depth;
|
|
2191
|
+
this.points = [];
|
|
2192
|
+
this.divided = false;
|
|
2193
|
+
}
|
|
2194
|
+
/**
|
|
2195
|
+
* Create a Quadtree from corner-based bounds (top-left + size).
|
|
2196
|
+
* Internally converts to center-based representation.
|
|
2197
|
+
*/
|
|
2198
|
+
static create(x, y, width, height, options) {
|
|
2199
|
+
const hw = width / 2;
|
|
2200
|
+
const hh = height / 2;
|
|
2201
|
+
return new _Quadtree(
|
|
2202
|
+
new Rectangle(x + hw, y + hh, hw, hh),
|
|
2203
|
+
options?.capacity ?? 4,
|
|
2204
|
+
options?.maxDepth ?? 8
|
|
2205
|
+
);
|
|
2331
2206
|
}
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
this.context.save();
|
|
2339
|
-
this.context.font = font;
|
|
2340
|
-
const metrics = this.context.measureText(text);
|
|
2341
|
-
this.context.restore();
|
|
2342
|
-
this.textMetricsCache.set(cacheKey, metrics);
|
|
2343
|
-
if (this.textMetricsCache.size > 1e3) {
|
|
2344
|
-
const firstKey = this.textMetricsCache.keys().next().value;
|
|
2345
|
-
if (firstKey) this.textMetricsCache.delete(firstKey);
|
|
2207
|
+
insert(point) {
|
|
2208
|
+
if (!this.boundary.contains(point)) return false;
|
|
2209
|
+
if (!this.divided) {
|
|
2210
|
+
if (this.points.length < this.capacity || this.depth >= this.maxDepth) {
|
|
2211
|
+
this.points.push(point);
|
|
2212
|
+
return true;
|
|
2346
2213
|
}
|
|
2214
|
+
this.subdivide();
|
|
2215
|
+
}
|
|
2216
|
+
return this.ne.insert(point) || this.nw.insert(point) || this.se.insert(point) || this.sw.insert(point);
|
|
2217
|
+
}
|
|
2218
|
+
subdivide() {
|
|
2219
|
+
const { x, y, w, h } = this.boundary;
|
|
2220
|
+
const hw = w / 2;
|
|
2221
|
+
const hh = h / 2;
|
|
2222
|
+
const d = this.depth + 1;
|
|
2223
|
+
this.ne = new _Quadtree(
|
|
2224
|
+
new Rectangle(x + hw, y - hh, hw, hh),
|
|
2225
|
+
this.capacity,
|
|
2226
|
+
this.maxDepth,
|
|
2227
|
+
d
|
|
2228
|
+
);
|
|
2229
|
+
this.nw = new _Quadtree(
|
|
2230
|
+
new Rectangle(x - hw, y - hh, hw, hh),
|
|
2231
|
+
this.capacity,
|
|
2232
|
+
this.maxDepth,
|
|
2233
|
+
d
|
|
2234
|
+
);
|
|
2235
|
+
this.se = new _Quadtree(
|
|
2236
|
+
new Rectangle(x + hw, y + hh, hw, hh),
|
|
2237
|
+
this.capacity,
|
|
2238
|
+
this.maxDepth,
|
|
2239
|
+
d
|
|
2240
|
+
);
|
|
2241
|
+
this.sw = new _Quadtree(
|
|
2242
|
+
new Rectangle(x - hw, y + hh, hw, hh),
|
|
2243
|
+
this.capacity,
|
|
2244
|
+
this.maxDepth,
|
|
2245
|
+
d
|
|
2246
|
+
);
|
|
2247
|
+
this.divided = true;
|
|
2248
|
+
for (const p of this.points) {
|
|
2249
|
+
this.ne.insert(p) || this.nw.insert(p) || this.se.insert(p) || this.sw.insert(p);
|
|
2347
2250
|
}
|
|
2348
|
-
|
|
2349
|
-
}
|
|
2350
|
-
/**
|
|
2351
|
-
* Clear all performance caches
|
|
2352
|
-
*/
|
|
2353
|
-
clearCaches() {
|
|
2354
|
-
this.textMetricsCache.clear();
|
|
2355
|
-
}
|
|
2356
|
-
/**
|
|
2357
|
-
* Get current performance metrics
|
|
2358
|
-
*/
|
|
2359
|
-
getMetrics() {
|
|
2360
|
-
return this.context.__performance || null;
|
|
2251
|
+
this.points = [];
|
|
2361
2252
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
const metrics = this.getMetrics();
|
|
2367
|
-
if (!metrics) return;
|
|
2368
|
-
const {
|
|
2369
|
-
x = 10,
|
|
2370
|
-
y = 10,
|
|
2371
|
-
width = 200,
|
|
2372
|
-
height = 120,
|
|
2373
|
-
backgroundColor = "rgba(0, 0, 0, 0.8)",
|
|
2374
|
-
textColor = "#ffffff",
|
|
2375
|
-
accentColor = "#4ecdc4",
|
|
2376
|
-
showGraph = true,
|
|
2377
|
-
graphHeight = 40,
|
|
2378
|
-
fontSize = 12,
|
|
2379
|
-
showMemory = true
|
|
2380
|
-
} = options;
|
|
2381
|
-
if (showGraph) {
|
|
2382
|
-
this.frameTimeHistory.push(metrics.frameTime);
|
|
2383
|
-
if (this.frameTimeHistory.length > this.MAX_HISTORY) {
|
|
2384
|
-
this.frameTimeHistory.shift();
|
|
2385
|
-
}
|
|
2253
|
+
query(range, found = []) {
|
|
2254
|
+
if (!this.boundary.intersects(range)) return found;
|
|
2255
|
+
for (const p of this.points) {
|
|
2256
|
+
if (range.contains(p)) found.push(p);
|
|
2386
2257
|
}
|
|
2387
|
-
this.
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
this.context.strokeRect(x, y, width, height);
|
|
2393
|
-
this.context.fillStyle = textColor;
|
|
2394
|
-
this.context.font = `${fontSize}px monospace`;
|
|
2395
|
-
this.context.textAlign = "left";
|
|
2396
|
-
this.context.textBaseline = "top";
|
|
2397
|
-
let currentY = y + 8;
|
|
2398
|
-
const fpsColor = metrics.fps >= 55 ? "#4ecdc4" : metrics.fps >= 30 ? "#ffd93d" : "#ff6b6b";
|
|
2399
|
-
this.context.fillStyle = fpsColor;
|
|
2400
|
-
this.context.fillText(`FPS: ${metrics.fps}`, x + 8, currentY);
|
|
2401
|
-
currentY += fontSize + 4;
|
|
2402
|
-
this.context.fillStyle = textColor;
|
|
2403
|
-
this.context.fillText(`Frame: ${metrics.frameTime.toFixed(2)}ms`, x + 8, currentY);
|
|
2404
|
-
currentY += fontSize + 4;
|
|
2405
|
-
this.context.fillText(`Avg: ${metrics.averageFrameTime.toFixed(2)}ms`, x + 8, currentY);
|
|
2406
|
-
currentY += fontSize + 4;
|
|
2407
|
-
this.context.fillText(
|
|
2408
|
-
`Min: ${metrics.minFrameTime.toFixed(2)}ms / Max: ${metrics.maxFrameTime.toFixed(2)}ms`,
|
|
2409
|
-
x + 8,
|
|
2410
|
-
currentY
|
|
2411
|
-
);
|
|
2412
|
-
currentY += fontSize + 4;
|
|
2413
|
-
if (metrics.droppedFrames > 0) {
|
|
2414
|
-
this.context.fillStyle = "#ff6b6b";
|
|
2415
|
-
this.context.fillText(`Dropped: ${metrics.droppedFrames}`, x + 8, currentY);
|
|
2416
|
-
currentY += fontSize + 4;
|
|
2258
|
+
if (this.divided) {
|
|
2259
|
+
this.ne.query(range, found);
|
|
2260
|
+
this.nw.query(range, found);
|
|
2261
|
+
this.se.query(range, found);
|
|
2262
|
+
this.sw.query(range, found);
|
|
2417
2263
|
}
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2264
|
+
return found;
|
|
2265
|
+
}
|
|
2266
|
+
queryRadius(cx, cy, radius, found = []) {
|
|
2267
|
+
if (!this.boundary.intersectsCircle(cx, cy, radius)) return found;
|
|
2268
|
+
const rSq = radius * radius;
|
|
2269
|
+
for (const p of this.points) {
|
|
2270
|
+
if ((p.x - cx) ** 2 + (p.y - cy) ** 2 <= rSq) found.push(p);
|
|
2422
2271
|
}
|
|
2423
|
-
if (
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
this.context.fillStyle = "rgba(255, 255, 255, 0.1)";
|
|
2429
|
-
this.context.fillRect(graphX, graphY, graphWidth, graphHeight);
|
|
2430
|
-
const targetY = graphY + graphHeight - targetFrameTime / (targetFrameTime * 2) * graphHeight;
|
|
2431
|
-
this.context.strokeStyle = "rgba(255, 255, 255, 0.3)";
|
|
2432
|
-
this.context.lineWidth = 1;
|
|
2433
|
-
this.context.beginPath();
|
|
2434
|
-
this.context.moveTo(graphX, targetY);
|
|
2435
|
-
this.context.lineTo(graphX + graphWidth, targetY);
|
|
2436
|
-
this.context.stroke();
|
|
2437
|
-
this.context.strokeStyle = accentColor;
|
|
2438
|
-
this.context.lineWidth = 2;
|
|
2439
|
-
this.context.beginPath();
|
|
2440
|
-
const maxFrameTime = Math.max(...this.frameTimeHistory, targetFrameTime * 2);
|
|
2441
|
-
const stepX = graphWidth / (this.frameTimeHistory.length - 1);
|
|
2442
|
-
this.frameTimeHistory.forEach((frameTime, index) => {
|
|
2443
|
-
const normalizedTime = Math.min(frameTime / maxFrameTime, 1);
|
|
2444
|
-
const pointY = graphY + graphHeight - normalizedTime * graphHeight;
|
|
2445
|
-
const pointX = graphX + index * stepX;
|
|
2446
|
-
if (index === 0) {
|
|
2447
|
-
this.context.moveTo(pointX, pointY);
|
|
2448
|
-
} else {
|
|
2449
|
-
this.context.lineTo(pointX, pointY);
|
|
2450
|
-
}
|
|
2451
|
-
});
|
|
2452
|
-
this.context.stroke();
|
|
2272
|
+
if (this.divided) {
|
|
2273
|
+
this.ne.queryRadius(cx, cy, radius, found);
|
|
2274
|
+
this.nw.queryRadius(cx, cy, radius, found);
|
|
2275
|
+
this.se.queryRadius(cx, cy, radius, found);
|
|
2276
|
+
this.sw.queryRadius(cx, cy, radius, found);
|
|
2453
2277
|
}
|
|
2454
|
-
|
|
2278
|
+
return found;
|
|
2455
2279
|
}
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2280
|
+
clear() {
|
|
2281
|
+
this.points = [];
|
|
2282
|
+
this.divided = false;
|
|
2283
|
+
this.ne = this.nw = this.se = this.sw = null;
|
|
2284
|
+
}
|
|
2285
|
+
get size() {
|
|
2286
|
+
let n = this.points.length;
|
|
2287
|
+
if (this.divided) {
|
|
2288
|
+
n += this.ne.size + this.nw.size + this.se.size + this.sw.size;
|
|
2289
|
+
}
|
|
2290
|
+
return n;
|
|
2461
2291
|
}
|
|
2462
2292
|
};
|
|
2463
|
-
var
|
|
2293
|
+
var Quadtree_default = Quadtree;
|
|
2464
2294
|
|
|
2465
|
-
// src/elements/
|
|
2466
|
-
var
|
|
2295
|
+
// src/elements/Pixels.tsx
|
|
2296
|
+
var Pixels = class {
|
|
2467
2297
|
constructor(ctx) {
|
|
2468
|
-
this.
|
|
2298
|
+
this.ctx = ctx;
|
|
2469
2299
|
}
|
|
2470
2300
|
/**
|
|
2471
|
-
*
|
|
2301
|
+
* Read all pixels from the canvas as ImageData.
|
|
2472
2302
|
*/
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
return this.renderInBrowser(draw, options);
|
|
2476
|
-
}
|
|
2477
|
-
throw new Error(
|
|
2478
|
-
"Server-side rendering requires 'canvas' package. Install it with: npm install canvas\nAlternatively, use SSR.generateImageUrl() to generate images via an API endpoint."
|
|
2479
|
-
);
|
|
2303
|
+
load() {
|
|
2304
|
+
return this.ctx.getImageData(0, 0, this.ctx.width, this.ctx.height);
|
|
2480
2305
|
}
|
|
2481
2306
|
/**
|
|
2482
|
-
*
|
|
2307
|
+
* Write pixel data back to the canvas.
|
|
2308
|
+
* Accepts a Uint8ClampedArray or a plain number array of RGBA values.
|
|
2483
2309
|
*/
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2310
|
+
update(pixels) {
|
|
2311
|
+
const pixelArray = pixels instanceof Uint8ClampedArray ? pixels : new Uint8ClampedArray(pixels);
|
|
2312
|
+
const imageData = new ImageData(
|
|
2313
|
+
new Uint8ClampedArray(pixelArray.buffer),
|
|
2314
|
+
this.ctx.width,
|
|
2315
|
+
this.ctx.height
|
|
2316
|
+
);
|
|
2317
|
+
this.ctx.putImageData(imageData, 0, 0);
|
|
2491
2318
|
}
|
|
2492
2319
|
/**
|
|
2493
|
-
*
|
|
2320
|
+
* Read pixel values at a position.
|
|
2321
|
+
* Returns an array of [r, g, b, a] values (0-255).
|
|
2322
|
+
*
|
|
2323
|
+
* @param x - X coordinate
|
|
2324
|
+
* @param y - Y coordinate
|
|
2325
|
+
* @param w - Width of region (default: 1)
|
|
2326
|
+
* @param h - Height of region (default: 1)
|
|
2494
2327
|
*/
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
}
|
|
2499
|
-
try {
|
|
2500
|
-
__require("canvas");
|
|
2501
|
-
return true;
|
|
2502
|
-
} catch {
|
|
2503
|
-
return false;
|
|
2504
|
-
}
|
|
2328
|
+
read(x, y, w = 1, h = 1) {
|
|
2329
|
+
const imageData = this.ctx.getImageData(x, y, w, h);
|
|
2330
|
+
return Array.from(imageData.data);
|
|
2505
2331
|
}
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2332
|
+
};
|
|
2333
|
+
|
|
2334
|
+
// src/elements/Timeline.tsx
|
|
2335
|
+
var Timeline = class {
|
|
2336
|
+
constructor() {
|
|
2337
|
+
this.callbacks = { start: [], end: [], loop: [] };
|
|
2338
|
+
}
|
|
2339
|
+
onStart(fn) {
|
|
2340
|
+
this.callbacks.start.push(fn);
|
|
2341
|
+
}
|
|
2342
|
+
onEnd(fn) {
|
|
2343
|
+
this.callbacks.end.push(fn);
|
|
2344
|
+
}
|
|
2345
|
+
onLoop(fn) {
|
|
2346
|
+
this.callbacks.loop.push(fn);
|
|
2347
|
+
}
|
|
2348
|
+
create(setup, options = {}) {
|
|
2349
|
+
const tracks = /* @__PURE__ */ new Map();
|
|
2350
|
+
let currentProgress = 0;
|
|
2351
|
+
let hasStarted = false;
|
|
2352
|
+
let hasEnded = false;
|
|
2353
|
+
const callbacks = this.callbacks;
|
|
2354
|
+
const defaultEasing = options.defaultEasing || ((t) => t);
|
|
2355
|
+
const defaultLoop = options.defaultLoop || 0;
|
|
2356
|
+
const executeCallback = (callback, errorMsg = "Callback error") => {
|
|
2511
2357
|
try {
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2358
|
+
callback();
|
|
2359
|
+
} catch (e) {
|
|
2360
|
+
console.warn(`${errorMsg}:`, e);
|
|
2361
|
+
}
|
|
2362
|
+
};
|
|
2363
|
+
function createKeyframes() {
|
|
2364
|
+
const segments = [];
|
|
2365
|
+
let currentPos = 0;
|
|
2366
|
+
let loopCount = defaultLoop;
|
|
2367
|
+
const parentTrack = void 0;
|
|
2368
|
+
const parseEasingCallback = (easing, callback) => {
|
|
2369
|
+
if (typeof easing === "function" && typeof callback === "undefined") {
|
|
2370
|
+
if (easing.length === 0) {
|
|
2371
|
+
return { easing: defaultEasing, callback: easing };
|
|
2372
|
+
}
|
|
2373
|
+
return {
|
|
2374
|
+
easing,
|
|
2375
|
+
callback: void 0
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
return {
|
|
2379
|
+
easing: easing || defaultEasing,
|
|
2380
|
+
callback
|
|
2381
|
+
};
|
|
2382
|
+
};
|
|
2383
|
+
const builder = {
|
|
2384
|
+
start(value, delay = 0, callback) {
|
|
2385
|
+
segments.push({ pos: delay, value, callback, type: "start" });
|
|
2386
|
+
currentPos = delay;
|
|
2387
|
+
return builder;
|
|
2388
|
+
},
|
|
2389
|
+
at(progress, value, easing, callback) {
|
|
2390
|
+
const { easing: finalEasing, callback: finalCallback } = parseEasingCallback(easing, callback);
|
|
2391
|
+
segments.push({
|
|
2392
|
+
pos: progress,
|
|
2393
|
+
value,
|
|
2394
|
+
easing: finalEasing,
|
|
2395
|
+
callback: finalCallback,
|
|
2396
|
+
type: "tween"
|
|
2397
|
+
});
|
|
2398
|
+
currentPos = progress;
|
|
2399
|
+
return builder;
|
|
2400
|
+
},
|
|
2401
|
+
then(value, duration, easing, callback) {
|
|
2402
|
+
const { easing: finalEasing, callback: finalCallback } = parseEasingCallback(easing, callback);
|
|
2403
|
+
const nextPos = currentPos + duration;
|
|
2404
|
+
segments.push({
|
|
2405
|
+
pos: nextPos,
|
|
2406
|
+
value,
|
|
2407
|
+
easing: finalEasing,
|
|
2408
|
+
callback: finalCallback,
|
|
2409
|
+
type: "tween"
|
|
2410
|
+
});
|
|
2411
|
+
currentPos = nextPos;
|
|
2412
|
+
return builder;
|
|
2413
|
+
},
|
|
2414
|
+
loop(count = Infinity) {
|
|
2415
|
+
loopCount = count;
|
|
2416
|
+
return builder;
|
|
2417
|
+
},
|
|
2418
|
+
_compile: () => {
|
|
2419
|
+
segments.sort((a, b) => a.pos - b.pos);
|
|
2420
|
+
return { segments, loopCount, parentTrack };
|
|
2421
|
+
}
|
|
2422
|
+
};
|
|
2423
|
+
return builder;
|
|
2424
|
+
}
|
|
2425
|
+
function interpolateTrack(compiled, progress) {
|
|
2426
|
+
const { segments } = compiled;
|
|
2427
|
+
if (!segments.length) return 0;
|
|
2428
|
+
progress = Math.max(0, Math.min(1, progress));
|
|
2429
|
+
const valueSegments = segments.filter(
|
|
2430
|
+
(seg) => seg.value !== void 0
|
|
2431
|
+
);
|
|
2432
|
+
if (!valueSegments.length) return 0;
|
|
2433
|
+
let prevSeg = valueSegments[0];
|
|
2434
|
+
for (let i = 1; i < valueSegments.length; i++) {
|
|
2435
|
+
const seg = valueSegments[i];
|
|
2436
|
+
if (progress <= seg.pos) {
|
|
2437
|
+
if (seg.type === "tween" && prevSeg.value !== void 0 && seg.value !== void 0) {
|
|
2438
|
+
const t = (progress - prevSeg.pos) / (seg.pos - prevSeg.pos);
|
|
2439
|
+
const easedT = seg.easing ? seg.easing(t) : t;
|
|
2440
|
+
return prevSeg.value + (seg.value - prevSeg.value) * easedT;
|
|
2441
|
+
}
|
|
2442
|
+
return seg.value || 0;
|
|
2443
|
+
}
|
|
2444
|
+
if (seg.value !== void 0) {
|
|
2445
|
+
prevSeg = seg;
|
|
2520
2446
|
}
|
|
2521
|
-
const klintContext = this.createMinimalContext(
|
|
2522
|
-
ctx,
|
|
2523
|
-
canvas,
|
|
2524
|
-
options.width,
|
|
2525
|
-
options.height,
|
|
2526
|
-
dpr
|
|
2527
|
-
);
|
|
2528
|
-
draw(klintContext);
|
|
2529
|
-
const mimeType = options.format === "jpeg" ? "image/jpeg" : options.format === "webp" ? "image/webp" : "image/png";
|
|
2530
|
-
const quality = options.quality !== void 0 ? options.quality : 0.85;
|
|
2531
|
-
const dataUrl = canvas.toDataURL(mimeType, quality);
|
|
2532
|
-
resolve(dataUrl);
|
|
2533
|
-
} catch (error) {
|
|
2534
|
-
reject(error);
|
|
2535
2447
|
}
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
arc: ctx.arc.bind(ctx),
|
|
2555
|
-
fill: ctx.fill.bind(ctx),
|
|
2556
|
-
stroke: ctx.stroke.bind(ctx),
|
|
2557
|
-
save: ctx.save.bind(ctx),
|
|
2558
|
-
restore: ctx.restore.bind(ctx),
|
|
2559
|
-
translate: ctx.translate.bind(ctx),
|
|
2560
|
-
rotate: ctx.rotate.bind(ctx),
|
|
2561
|
-
scale: ctx.scale.bind(ctx),
|
|
2562
|
-
// Basic properties
|
|
2563
|
-
fillStyle: ctx.fillStyle,
|
|
2564
|
-
strokeStyle: ctx.strokeStyle,
|
|
2565
|
-
lineWidth: ctx.lineWidth,
|
|
2566
|
-
// Minimal Klint-like API
|
|
2567
|
-
background: (color) => {
|
|
2568
|
-
ctx.fillStyle = color || "#000";
|
|
2569
|
-
ctx.fillRect(0, 0, width * dpr, height * dpr);
|
|
2570
|
-
},
|
|
2571
|
-
fillColor: (color) => {
|
|
2572
|
-
ctx.fillStyle = color;
|
|
2448
|
+
return prevSeg.value || 0;
|
|
2449
|
+
}
|
|
2450
|
+
const timeline = {
|
|
2451
|
+
track: (keyframesOrFn) => {
|
|
2452
|
+
const compiled = typeof keyframesOrFn === "function" ? timeline.keyframes(keyframesOrFn) : keyframesOrFn;
|
|
2453
|
+
const track = {
|
|
2454
|
+
...compiled,
|
|
2455
|
+
currentValue: 0,
|
|
2456
|
+
getValue: (progress) => interpolateTrack(compiled, progress),
|
|
2457
|
+
get current() {
|
|
2458
|
+
return this.currentValue;
|
|
2459
|
+
},
|
|
2460
|
+
value() {
|
|
2461
|
+
return this.currentValue;
|
|
2462
|
+
}
|
|
2463
|
+
};
|
|
2464
|
+
tracks.set(track, compiled);
|
|
2465
|
+
return track;
|
|
2573
2466
|
},
|
|
2574
|
-
|
|
2575
|
-
|
|
2467
|
+
keyframes: (fn) => {
|
|
2468
|
+
const kf = createKeyframes();
|
|
2469
|
+
fn(kf);
|
|
2470
|
+
return kf._compile();
|
|
2576
2471
|
},
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2472
|
+
stagger: (count, offset, keyframesFn) => {
|
|
2473
|
+
const compiled = timeline.keyframes(keyframesFn);
|
|
2474
|
+
return Array.from({ length: count }, (_, i) => {
|
|
2475
|
+
const track = {
|
|
2476
|
+
...compiled,
|
|
2477
|
+
currentValue: 0,
|
|
2478
|
+
staggerDelay: i * offset,
|
|
2479
|
+
getValue: (progress) => {
|
|
2480
|
+
const staggeredProgress = Math.max(0, progress - i * offset);
|
|
2481
|
+
const normalizedProgress = Math.min(
|
|
2482
|
+
1,
|
|
2483
|
+
staggeredProgress / (1 - i * offset)
|
|
2484
|
+
);
|
|
2485
|
+
return normalizedProgress > 0 ? interpolateTrack(compiled, normalizedProgress) : 0;
|
|
2486
|
+
},
|
|
2487
|
+
get current() {
|
|
2488
|
+
return this.currentValue;
|
|
2489
|
+
},
|
|
2490
|
+
value() {
|
|
2491
|
+
return this.currentValue;
|
|
2492
|
+
}
|
|
2493
|
+
};
|
|
2494
|
+
tracks.set(track, compiled);
|
|
2495
|
+
return track;
|
|
2496
|
+
});
|
|
2581
2497
|
},
|
|
2582
|
-
|
|
2583
|
-
|
|
2498
|
+
update: (progress) => {
|
|
2499
|
+
const prevProgress = currentProgress;
|
|
2500
|
+
currentProgress = progress;
|
|
2501
|
+
if (!hasStarted && progress > 0) {
|
|
2502
|
+
hasStarted = true;
|
|
2503
|
+
callbacks.start.forEach(
|
|
2504
|
+
(cb) => executeCallback(cb, "Start callback error")
|
|
2505
|
+
);
|
|
2506
|
+
}
|
|
2507
|
+
if (!hasEnded && progress >= 1) {
|
|
2508
|
+
hasEnded = true;
|
|
2509
|
+
callbacks.end.forEach(
|
|
2510
|
+
(cb) => executeCallback(cb, "End callback error")
|
|
2511
|
+
);
|
|
2512
|
+
}
|
|
2513
|
+
if (progress < prevProgress) {
|
|
2514
|
+
if (progress === 0) {
|
|
2515
|
+
hasStarted = false;
|
|
2516
|
+
hasEnded = false;
|
|
2517
|
+
} else if (progress < 1) {
|
|
2518
|
+
hasEnded = false;
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
for (const [track, compiled] of tracks) {
|
|
2522
|
+
track.currentValue = track.getValue(progress);
|
|
2523
|
+
if (compiled.segments) {
|
|
2524
|
+
compiled.segments.forEach((seg) => {
|
|
2525
|
+
if (seg.callback && seg.pos <= progress && seg.pos > prevProgress) {
|
|
2526
|
+
executeCallback(seg.callback);
|
|
2527
|
+
}
|
|
2528
|
+
});
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2584
2531
|
},
|
|
2585
|
-
|
|
2586
|
-
frame: 0,
|
|
2587
|
-
time: 0,
|
|
2588
|
-
deltaTime: 0,
|
|
2589
|
-
fps: 60
|
|
2532
|
+
progress: () => currentProgress
|
|
2590
2533
|
};
|
|
2534
|
+
const result = setup(timeline);
|
|
2535
|
+
return { ...result, update: timeline.update };
|
|
2591
2536
|
}
|
|
2592
2537
|
};
|
|
2593
|
-
var SSR_default = SSR;
|
|
2594
2538
|
|
|
2595
2539
|
// src/KlintFunctions.tsx
|
|
2596
2540
|
var KlintCoreFunctions = {
|
|
@@ -2612,37 +2556,6 @@ var KlintCoreFunctions = {
|
|
|
2612
2556
|
// to do
|
|
2613
2557
|
redraw: () => () => {
|
|
2614
2558
|
},
|
|
2615
|
-
extend: (ctx) => (name, data, enforceReplace = false) => {
|
|
2616
|
-
if (name in ctx && !enforceReplace) return;
|
|
2617
|
-
ctx[name] = data;
|
|
2618
|
-
},
|
|
2619
|
-
passImage: () => (element) => {
|
|
2620
|
-
if (!element.complete) {
|
|
2621
|
-
console.warn("Image passed to passImage() is not fully loaded");
|
|
2622
|
-
return null;
|
|
2623
|
-
}
|
|
2624
|
-
return element;
|
|
2625
|
-
},
|
|
2626
|
-
passImages: () => (elements) => {
|
|
2627
|
-
return elements.map((element) => {
|
|
2628
|
-
if (!element.complete) {
|
|
2629
|
-
console.warn("Image passed to passImages() is not fully loaded");
|
|
2630
|
-
return null;
|
|
2631
|
-
}
|
|
2632
|
-
return element;
|
|
2633
|
-
});
|
|
2634
|
-
},
|
|
2635
|
-
saveConfig: (ctx) => (from) => {
|
|
2636
|
-
return Object.fromEntries(
|
|
2637
|
-
CONFIG_PROPS.map((key) => [
|
|
2638
|
-
key,
|
|
2639
|
-
from?.[key] ?? ctx[key]
|
|
2640
|
-
])
|
|
2641
|
-
);
|
|
2642
|
-
},
|
|
2643
|
-
restoreConfig: (ctx) => (config) => {
|
|
2644
|
-
Object.assign(ctx, config);
|
|
2645
|
-
},
|
|
2646
2559
|
describe: (ctx) => (description) => {
|
|
2647
2560
|
ctx.__description = description;
|
|
2648
2561
|
},
|
|
@@ -2747,6 +2660,7 @@ var KlintFunctions = {
|
|
|
2747
2660
|
strokeWidth: (ctx) => (width) => {
|
|
2748
2661
|
if (width <= 0) {
|
|
2749
2662
|
ctx.lineWidth = EPSILON;
|
|
2663
|
+
return;
|
|
2750
2664
|
}
|
|
2751
2665
|
ctx.lineWidth = width;
|
|
2752
2666
|
},
|
|
@@ -2923,7 +2837,7 @@ var KlintFunctions = {
|
|
|
2923
2837
|
ctx.__currentContours = null;
|
|
2924
2838
|
ctx.__startedShape = false;
|
|
2925
2839
|
},
|
|
2926
|
-
gradient: (ctx) => (x1 = 0, y1 = 0, x2 = ctx.width, y2 = ctx.
|
|
2840
|
+
gradient: (ctx) => (x1 = 0, y1 = 0, x2 = ctx.width, y2 = ctx.height) => {
|
|
2927
2841
|
return ctx.createLinearGradient(x1, y1, x2, y2);
|
|
2928
2842
|
},
|
|
2929
2843
|
radialGradient: (ctx) => (x1 = ctx.width / 2, y1 = ctx.height / 2, r1 = 0, x2 = ctx.width / 2, y2 = ctx.height / 2, r2 = Math.min(ctx.width, ctx.height)) => {
|
|
@@ -3186,19 +3100,6 @@ var KlintFunctions = {
|
|
|
3186
3100
|
const adjustedY = ctx.__imageOrigin === "center" ? dy - height / 2 : dy;
|
|
3187
3101
|
ctx.drawImage(sourceImage, adjustedX, adjustedY);
|
|
3188
3102
|
},
|
|
3189
|
-
// unsure about keeping those next two, maybe a shader plugin would be better
|
|
3190
|
-
loadPixels: (ctx) => () => {
|
|
3191
|
-
return ctx.getImageData(0, 0, ctx.width, ctx.height);
|
|
3192
|
-
},
|
|
3193
|
-
updatePixels: (ctx) => (pixels) => {
|
|
3194
|
-
const pixelArray = pixels instanceof Uint8ClampedArray ? new Uint8ClampedArray(pixels) : new Uint8ClampedArray(pixels);
|
|
3195
|
-
const imageData = new ImageData(pixelArray, ctx.width, ctx.height);
|
|
3196
|
-
ctx.putImageData(imageData, 0, 0);
|
|
3197
|
-
},
|
|
3198
|
-
readPixels: (ctx) => (x, y, w = 1, h = 1) => {
|
|
3199
|
-
const imageData = ctx.getImageData(x, y, w, h);
|
|
3200
|
-
return Array.from(imageData.data);
|
|
3201
|
-
},
|
|
3202
3103
|
scaleTo: () => (originWidth, originHeight, destinationWidth, destinationHeight, cover = false) => {
|
|
3203
3104
|
const widthRatio = destinationWidth / originWidth;
|
|
3204
3105
|
const heightRatio = destinationHeight / originHeight;
|
|
@@ -3210,6 +3111,12 @@ var KlintFunctions = {
|
|
|
3210
3111
|
blend: (ctx) => (blend) => {
|
|
3211
3112
|
ctx.globalCompositeOperation = blend === "default" ? "source-over" : blend;
|
|
3212
3113
|
},
|
|
3114
|
+
smooth: (ctx) => () => {
|
|
3115
|
+
ctx.imageSmoothingEnabled = true;
|
|
3116
|
+
},
|
|
3117
|
+
noSmooth: (ctx) => () => {
|
|
3118
|
+
ctx.imageSmoothingEnabled = false;
|
|
3119
|
+
},
|
|
3213
3120
|
setCanvasOrigin: (ctx) => (type) => {
|
|
3214
3121
|
ctx.__canvasOrigin = type;
|
|
3215
3122
|
},
|
|
@@ -3273,6 +3180,41 @@ var KlintFunctions = {
|
|
|
3273
3180
|
ctx.fill = originalFill;
|
|
3274
3181
|
ctx.stroke = originalStroke;
|
|
3275
3182
|
},
|
|
3183
|
+
screenToWorld: (ctx) => (screenX, screenY) => {
|
|
3184
|
+
const isCenter = ctx.__canvasOrigin === "center";
|
|
3185
|
+
const deviceX = isCenter ? screenX + ctx.width * 0.5 : screenX;
|
|
3186
|
+
const deviceY = isCenter ? screenY + ctx.height * 0.5 : screenY;
|
|
3187
|
+
const inverse = ctx.getTransform().inverse();
|
|
3188
|
+
const pt = inverse.transformPoint(new DOMPoint(deviceX, deviceY));
|
|
3189
|
+
return { x: pt.x, y: pt.y };
|
|
3190
|
+
},
|
|
3191
|
+
worldToScreen: (ctx) => (worldX, worldY) => {
|
|
3192
|
+
const isCenter = ctx.__canvasOrigin === "center";
|
|
3193
|
+
const matrix = ctx.getTransform();
|
|
3194
|
+
const pt = matrix.transformPoint(new DOMPoint(worldX, worldY));
|
|
3195
|
+
const screenX = isCenter ? pt.x - ctx.width * 0.5 : pt.x;
|
|
3196
|
+
const screenY = isCenter ? pt.y - ctx.height * 0.5 : pt.y;
|
|
3197
|
+
return { x: screenX, y: screenY };
|
|
3198
|
+
},
|
|
3199
|
+
getVisibleBounds: (ctx) => () => {
|
|
3200
|
+
const inverse = ctx.getTransform().inverse();
|
|
3201
|
+
const c0 = inverse.transformPoint(new DOMPoint(0, 0));
|
|
3202
|
+
const c1 = inverse.transformPoint(new DOMPoint(ctx.width, 0));
|
|
3203
|
+
const c2 = inverse.transformPoint(new DOMPoint(ctx.width, ctx.height));
|
|
3204
|
+
const c3 = inverse.transformPoint(new DOMPoint(0, ctx.height));
|
|
3205
|
+
const left = Math.min(c0.x, c1.x, c2.x, c3.x);
|
|
3206
|
+
const right = Math.max(c0.x, c1.x, c2.x, c3.x);
|
|
3207
|
+
const top = Math.min(c0.y, c1.y, c2.y, c3.y);
|
|
3208
|
+
const bottom = Math.max(c0.y, c1.y, c2.y, c3.y);
|
|
3209
|
+
return {
|
|
3210
|
+
left,
|
|
3211
|
+
top,
|
|
3212
|
+
right,
|
|
3213
|
+
bottom,
|
|
3214
|
+
width: right - left,
|
|
3215
|
+
height: bottom - top
|
|
3216
|
+
};
|
|
3217
|
+
},
|
|
3276
3218
|
canIuseFilter: (ctx) => () => {
|
|
3277
3219
|
return ctx.filter !== void 0 && ctx.filter !== null;
|
|
3278
3220
|
},
|
|
@@ -3363,29 +3305,8 @@ function useKlint() {
|
|
|
3363
3305
|
const gestureRef = useRef2(null);
|
|
3364
3306
|
const keyboardRef = useRef2(null);
|
|
3365
3307
|
const useDev = () => {
|
|
3366
|
-
useEffect2(() => {
|
|
3367
|
-
if (process.env.NODE_ENV === "development") {
|
|
3368
|
-
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
3369
|
-
console.log("[Klint] hot updated - clearing non-context state");
|
|
3370
|
-
if (contextRef.current) {
|
|
3371
|
-
const ctx = contextRef.current;
|
|
3372
|
-
ctx.frame = 0;
|
|
3373
|
-
ctx.time = 0;
|
|
3374
|
-
ctx.__offscreens?.clear();
|
|
3375
|
-
ctx.__startedShape = false;
|
|
3376
|
-
ctx.__currentShape = null;
|
|
3377
|
-
ctx.__startedContour = false;
|
|
3378
|
-
ctx.__currentContours = null;
|
|
3379
|
-
ctx.__currentContour = null;
|
|
3380
|
-
ctx.__isReadyToDraw = true;
|
|
3381
|
-
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
3382
|
-
}
|
|
3383
|
-
}
|
|
3384
|
-
}
|
|
3385
|
-
}, []);
|
|
3386
3308
|
useEffect2(() => {
|
|
3387
3309
|
if (process.env.NODE_ENV === "development" && contextRef.current) {
|
|
3388
|
-
console.log("[Klint] hot updated - clearing context state");
|
|
3389
3310
|
contextRef.current.__isReadyToDraw = true;
|
|
3390
3311
|
}
|
|
3391
3312
|
});
|
|
@@ -3509,7 +3430,7 @@ function useKlint() {
|
|
|
3509
3430
|
canvas.addEventListener("mouseleave", handleMouseLeave, { signal });
|
|
3510
3431
|
canvas.addEventListener("click", handleClick, { signal });
|
|
3511
3432
|
return () => controller.abort();
|
|
3512
|
-
});
|
|
3433
|
+
}, []);
|
|
3513
3434
|
return {
|
|
3514
3435
|
mouse: mouseRef.current,
|
|
3515
3436
|
onClick: (callback) => clickCallbackRef.current = callback,
|
|
@@ -3544,7 +3465,7 @@ function useKlint() {
|
|
|
3544
3465
|
};
|
|
3545
3466
|
canvas.addEventListener("wheel", handleScroll, { signal });
|
|
3546
3467
|
return () => controller.abort();
|
|
3547
|
-
});
|
|
3468
|
+
}, []);
|
|
3548
3469
|
return {
|
|
3549
3470
|
scroll: scrollRef.current,
|
|
3550
3471
|
onScroll: (callback) => scrollCallbackRef.current = callback
|
|
@@ -3721,6 +3642,17 @@ function useKlint() {
|
|
|
3721
3642
|
const keyPressedCallbackRef = useRef2(/* @__PURE__ */ new Map());
|
|
3722
3643
|
const keyReleasedCallbackRef = useRef2(/* @__PURE__ */ new Map());
|
|
3723
3644
|
const keyComboCallbackRef = useRef2(/* @__PURE__ */ new Map());
|
|
3645
|
+
const normalizeKey = (key) => {
|
|
3646
|
+
const keyMap = {
|
|
3647
|
+
" ": "Space",
|
|
3648
|
+
Control: "Ctrl",
|
|
3649
|
+
Escape: "Esc"
|
|
3650
|
+
};
|
|
3651
|
+
return keyMap[key] || key;
|
|
3652
|
+
};
|
|
3653
|
+
const createComboKey = (keys) => {
|
|
3654
|
+
return keys.map(normalizeKey).sort().join("+");
|
|
3655
|
+
};
|
|
3724
3656
|
useEffect2(() => {
|
|
3725
3657
|
if (!contextRef.current) return;
|
|
3726
3658
|
const ctx = contextRef.current;
|
|
@@ -3733,17 +3665,9 @@ function useKlint() {
|
|
|
3733
3665
|
keyboardRef.current.modifiers.ctrl = e.ctrlKey;
|
|
3734
3666
|
keyboardRef.current.modifiers.meta = e.metaKey;
|
|
3735
3667
|
};
|
|
3736
|
-
const normalizeKey2 = (key) => {
|
|
3737
|
-
const keyMap = {
|
|
3738
|
-
" ": "Space",
|
|
3739
|
-
Control: "Ctrl",
|
|
3740
|
-
Escape: "Esc"
|
|
3741
|
-
};
|
|
3742
|
-
return keyMap[key] || key;
|
|
3743
|
-
};
|
|
3744
3668
|
const handleKeyDown = (e) => {
|
|
3745
3669
|
if (!keyboardRef.current) return;
|
|
3746
|
-
const normalizedKey =
|
|
3670
|
+
const normalizedKey = normalizeKey(e.key);
|
|
3747
3671
|
keyboardRef.current.pressedKeys.add(normalizedKey);
|
|
3748
3672
|
keyboardRef.current.lastKey = normalizedKey;
|
|
3749
3673
|
keyboardRef.current.lastKeyTime = performance.now();
|
|
@@ -3763,7 +3687,7 @@ function useKlint() {
|
|
|
3763
3687
|
};
|
|
3764
3688
|
const handleKeyUp = (e) => {
|
|
3765
3689
|
if (!keyboardRef.current) return;
|
|
3766
|
-
const normalizedKey =
|
|
3690
|
+
const normalizedKey = normalizeKey(e.key);
|
|
3767
3691
|
keyboardRef.current.pressedKeys.delete(normalizedKey);
|
|
3768
3692
|
updateModifiers(e);
|
|
3769
3693
|
const keyCallback = keyReleasedCallbackRef.current.get(normalizedKey);
|
|
@@ -3775,17 +3699,6 @@ function useKlint() {
|
|
|
3775
3699
|
window.addEventListener("keyup", handleKeyUp, { signal });
|
|
3776
3700
|
return () => controller.abort();
|
|
3777
3701
|
}, []);
|
|
3778
|
-
const createComboKey = (keys) => {
|
|
3779
|
-
return keys.map(normalizeKey).sort().join("+");
|
|
3780
|
-
};
|
|
3781
|
-
const normalizeKey = (key) => {
|
|
3782
|
-
const keyMap = {
|
|
3783
|
-
" ": "Space",
|
|
3784
|
-
Control: "Ctrl",
|
|
3785
|
-
Escape: "Esc"
|
|
3786
|
-
};
|
|
3787
|
-
return keyMap[key] || key;
|
|
3788
|
-
};
|
|
3789
3702
|
return {
|
|
3790
3703
|
keyboard: keyboardRef.current,
|
|
3791
3704
|
// Register callback for single key press
|
|
@@ -3819,210 +3732,6 @@ function useKlint() {
|
|
|
3819
3732
|
}
|
|
3820
3733
|
};
|
|
3821
3734
|
};
|
|
3822
|
-
const KlintTimeline = () => {
|
|
3823
|
-
const timelinesRef = useRef2(/* @__PURE__ */ new Map());
|
|
3824
|
-
const callbacksRef = useRef2({ start: [], end: [], loop: [] });
|
|
3825
|
-
const Timeline = {
|
|
3826
|
-
create: (setup, options = {}) => {
|
|
3827
|
-
const tracks = /* @__PURE__ */ new Map();
|
|
3828
|
-
const parents = /* @__PURE__ */ new Set();
|
|
3829
|
-
let currentProgress = 0;
|
|
3830
|
-
let hasStarted = false;
|
|
3831
|
-
let hasEnded = false;
|
|
3832
|
-
const defaultEasing = options.defaultEasing || ((t) => t);
|
|
3833
|
-
const defaultLoop = options.defaultLoop || 0;
|
|
3834
|
-
const executeCallback = (callback, errorMsg = "Callback error") => {
|
|
3835
|
-
try {
|
|
3836
|
-
callback();
|
|
3837
|
-
} catch (e) {
|
|
3838
|
-
console.warn(`${errorMsg}:`, e);
|
|
3839
|
-
}
|
|
3840
|
-
};
|
|
3841
|
-
function createKeyframes() {
|
|
3842
|
-
const segments = [];
|
|
3843
|
-
let currentPos = 0;
|
|
3844
|
-
let loopCount = defaultLoop;
|
|
3845
|
-
let parentTrack = void 0;
|
|
3846
|
-
const parseEasingCallback = (easing, callback) => {
|
|
3847
|
-
if (typeof easing === "function" && typeof callback === "undefined") {
|
|
3848
|
-
if (easing.length === 0) {
|
|
3849
|
-
return {
|
|
3850
|
-
easing: defaultEasing,
|
|
3851
|
-
callback: easing
|
|
3852
|
-
};
|
|
3853
|
-
}
|
|
3854
|
-
return {
|
|
3855
|
-
easing,
|
|
3856
|
-
callback: void 0
|
|
3857
|
-
};
|
|
3858
|
-
}
|
|
3859
|
-
return {
|
|
3860
|
-
easing: easing || defaultEasing,
|
|
3861
|
-
callback
|
|
3862
|
-
};
|
|
3863
|
-
};
|
|
3864
|
-
const builder = {
|
|
3865
|
-
start(value, delay = 0, callback) {
|
|
3866
|
-
segments.push({ pos: delay, value, callback, type: "start" });
|
|
3867
|
-
currentPos = delay;
|
|
3868
|
-
return builder;
|
|
3869
|
-
},
|
|
3870
|
-
at(progress, value, easing, callback) {
|
|
3871
|
-
const { easing: finalEasing, callback: finalCallback } = parseEasingCallback(easing, callback);
|
|
3872
|
-
segments.push({
|
|
3873
|
-
pos: progress,
|
|
3874
|
-
value,
|
|
3875
|
-
easing: finalEasing,
|
|
3876
|
-
callback: finalCallback,
|
|
3877
|
-
type: "tween"
|
|
3878
|
-
});
|
|
3879
|
-
currentPos = progress;
|
|
3880
|
-
return builder;
|
|
3881
|
-
},
|
|
3882
|
-
then(value, duration, easing, callback) {
|
|
3883
|
-
const { easing: finalEasing, callback: finalCallback } = parseEasingCallback(easing, callback);
|
|
3884
|
-
const nextPos = currentPos + duration;
|
|
3885
|
-
segments.push({
|
|
3886
|
-
pos: nextPos,
|
|
3887
|
-
value,
|
|
3888
|
-
easing: finalEasing,
|
|
3889
|
-
callback: finalCallback,
|
|
3890
|
-
type: "tween"
|
|
3891
|
-
});
|
|
3892
|
-
currentPos = nextPos;
|
|
3893
|
-
return builder;
|
|
3894
|
-
},
|
|
3895
|
-
loop(count = Infinity) {
|
|
3896
|
-
loopCount = count;
|
|
3897
|
-
return builder;
|
|
3898
|
-
},
|
|
3899
|
-
_compile: () => {
|
|
3900
|
-
segments.sort((a, b) => a.pos - b.pos);
|
|
3901
|
-
return { segments, loopCount, parentTrack };
|
|
3902
|
-
}
|
|
3903
|
-
};
|
|
3904
|
-
return builder;
|
|
3905
|
-
}
|
|
3906
|
-
function interpolateTrack(compiled, progress) {
|
|
3907
|
-
const { segments } = compiled;
|
|
3908
|
-
if (!segments.length) return 0;
|
|
3909
|
-
progress = Math.max(0, Math.min(1, progress));
|
|
3910
|
-
const valueSegments = segments.filter(
|
|
3911
|
-
(seg) => seg.type !== "callback"
|
|
3912
|
-
);
|
|
3913
|
-
if (!valueSegments.length) return 0;
|
|
3914
|
-
let prevSeg = valueSegments[0];
|
|
3915
|
-
for (let i = 1; i < valueSegments.length; i++) {
|
|
3916
|
-
const seg = valueSegments[i];
|
|
3917
|
-
if (progress <= seg.pos) {
|
|
3918
|
-
if (seg.type === "tween" && prevSeg.value !== void 0 && seg.value !== void 0) {
|
|
3919
|
-
const t = (progress - prevSeg.pos) / (seg.pos - prevSeg.pos);
|
|
3920
|
-
const easedT = seg.easing ? seg.easing(t) : t;
|
|
3921
|
-
return prevSeg.value + (seg.value - prevSeg.value) * easedT;
|
|
3922
|
-
}
|
|
3923
|
-
return seg.value || 0;
|
|
3924
|
-
}
|
|
3925
|
-
if (seg.value !== void 0) {
|
|
3926
|
-
prevSeg = seg;
|
|
3927
|
-
}
|
|
3928
|
-
}
|
|
3929
|
-
return prevSeg.value || 0;
|
|
3930
|
-
}
|
|
3931
|
-
const timeline = {
|
|
3932
|
-
track: (keyframesOrFn) => {
|
|
3933
|
-
const compiled = typeof keyframesOrFn === "function" ? timeline.keyframes(keyframesOrFn) : keyframesOrFn;
|
|
3934
|
-
const track = {
|
|
3935
|
-
...compiled,
|
|
3936
|
-
currentValue: 0,
|
|
3937
|
-
getValue: (progress) => interpolateTrack(compiled, progress),
|
|
3938
|
-
get current() {
|
|
3939
|
-
return this.currentValue;
|
|
3940
|
-
},
|
|
3941
|
-
value: function() {
|
|
3942
|
-
return this.currentValue;
|
|
3943
|
-
}
|
|
3944
|
-
};
|
|
3945
|
-
tracks.set(track, compiled);
|
|
3946
|
-
return track;
|
|
3947
|
-
},
|
|
3948
|
-
keyframes: (fn) => {
|
|
3949
|
-
const kf = createKeyframes();
|
|
3950
|
-
fn(kf);
|
|
3951
|
-
return kf._compile();
|
|
3952
|
-
},
|
|
3953
|
-
stagger: (count, offset, keyframesFn) => {
|
|
3954
|
-
const compiled = timeline.keyframes(keyframesFn);
|
|
3955
|
-
return Array.from({ length: count }, (_, i) => {
|
|
3956
|
-
const track = {
|
|
3957
|
-
...compiled,
|
|
3958
|
-
currentValue: 0,
|
|
3959
|
-
staggerDelay: i * offset,
|
|
3960
|
-
getValue: (progress) => {
|
|
3961
|
-
const staggeredProgress = Math.max(0, progress - i * offset);
|
|
3962
|
-
const normalizedProgress = Math.min(
|
|
3963
|
-
1,
|
|
3964
|
-
staggeredProgress / (1 - i * offset)
|
|
3965
|
-
);
|
|
3966
|
-
return normalizedProgress > 0 ? interpolateTrack(compiled, normalizedProgress) : 0;
|
|
3967
|
-
},
|
|
3968
|
-
get current() {
|
|
3969
|
-
return this.currentValue;
|
|
3970
|
-
},
|
|
3971
|
-
value: function() {
|
|
3972
|
-
return this.currentValue;
|
|
3973
|
-
}
|
|
3974
|
-
};
|
|
3975
|
-
tracks.set(track, compiled);
|
|
3976
|
-
return track;
|
|
3977
|
-
});
|
|
3978
|
-
},
|
|
3979
|
-
update: (progress) => {
|
|
3980
|
-
const prevProgress = currentProgress;
|
|
3981
|
-
currentProgress = progress;
|
|
3982
|
-
if (!hasStarted && progress > 0) {
|
|
3983
|
-
hasStarted = true;
|
|
3984
|
-
callbacksRef.current.start.forEach(
|
|
3985
|
-
(cb) => executeCallback(cb, "Start callback error")
|
|
3986
|
-
);
|
|
3987
|
-
}
|
|
3988
|
-
if (!hasEnded && progress >= 1) {
|
|
3989
|
-
hasEnded = true;
|
|
3990
|
-
callbacksRef.current.end.forEach(
|
|
3991
|
-
(cb) => executeCallback(cb, "End callback error")
|
|
3992
|
-
);
|
|
3993
|
-
}
|
|
3994
|
-
if (progress < prevProgress) {
|
|
3995
|
-
if (progress === 0) {
|
|
3996
|
-
hasStarted = false;
|
|
3997
|
-
hasEnded = false;
|
|
3998
|
-
} else if (progress < 1) {
|
|
3999
|
-
hasEnded = false;
|
|
4000
|
-
}
|
|
4001
|
-
}
|
|
4002
|
-
for (const [track, compiled] of tracks) {
|
|
4003
|
-
track.currentValue = track.getValue(progress);
|
|
4004
|
-
if (compiled.segments) {
|
|
4005
|
-
compiled.segments.forEach((seg) => {
|
|
4006
|
-
if (seg.callback && seg.pos <= progress && seg.pos > prevProgress) {
|
|
4007
|
-
executeCallback(seg.callback);
|
|
4008
|
-
}
|
|
4009
|
-
});
|
|
4010
|
-
}
|
|
4011
|
-
}
|
|
4012
|
-
},
|
|
4013
|
-
progress: () => currentProgress
|
|
4014
|
-
};
|
|
4015
|
-
const result = setup(timeline);
|
|
4016
|
-
return { ...result, update: timeline.update };
|
|
4017
|
-
}
|
|
4018
|
-
};
|
|
4019
|
-
return {
|
|
4020
|
-
Timeline,
|
|
4021
|
-
onStart: (fn) => callbacksRef.current.start.push(fn),
|
|
4022
|
-
onEnd: (fn) => callbacksRef.current.end.push(fn),
|
|
4023
|
-
onLoop: (fn) => callbacksRef.current.loop.push(fn)
|
|
4024
|
-
};
|
|
4025
|
-
};
|
|
4026
3735
|
const KlintWindow = () => {
|
|
4027
3736
|
const resizeCallbackRef = useRef2(
|
|
4028
3737
|
null
|
|
@@ -4093,13 +3802,13 @@ function useKlint() {
|
|
|
4093
3802
|
context.Vector = new Vector_default();
|
|
4094
3803
|
context.Easing = new Easing_default();
|
|
4095
3804
|
context.Text = new Text_default(context);
|
|
4096
|
-
context.Thing = new Thing_default(context);
|
|
4097
3805
|
context.Grid = new Grid_default(context);
|
|
4098
3806
|
context.Strip = new Strip_default(context);
|
|
4099
3807
|
context.Noise = new Noise_default(context);
|
|
4100
3808
|
context.Hotspot = new Hotspot_default(context);
|
|
4101
|
-
context.
|
|
4102
|
-
context.
|
|
3809
|
+
context.Quadtree = Quadtree_default;
|
|
3810
|
+
context.Pixels = new Pixels(context);
|
|
3811
|
+
context.Timeline = new Timeline();
|
|
4103
3812
|
Object.entries(KlintCoreFunctions).forEach(([name, fn]) => {
|
|
4104
3813
|
context[name] = fn(context);
|
|
4105
3814
|
});
|
|
@@ -4130,30 +3839,6 @@ function useKlint() {
|
|
|
4130
3839
|
contextRef.current.__isPlaying = !contextRef.current.__isPlaying;
|
|
4131
3840
|
}
|
|
4132
3841
|
}, []);
|
|
4133
|
-
const KlintPerformance = () => {
|
|
4134
|
-
const metricsRef = useRef2(null);
|
|
4135
|
-
useEffect2(() => {
|
|
4136
|
-
if (!contextRef.current?.__performance) return;
|
|
4137
|
-
const updateMetrics = () => {
|
|
4138
|
-
if (contextRef.current?.__performance) {
|
|
4139
|
-
metricsRef.current = { ...contextRef.current.__performance };
|
|
4140
|
-
}
|
|
4141
|
-
};
|
|
4142
|
-
const interval = setInterval(updateMetrics, 100);
|
|
4143
|
-
return () => clearInterval(interval);
|
|
4144
|
-
}, []);
|
|
4145
|
-
return {
|
|
4146
|
-
metrics: metricsRef.current,
|
|
4147
|
-
getMetrics: () => contextRef.current?.__performance || null,
|
|
4148
|
-
reset: () => {
|
|
4149
|
-
if (contextRef.current?.__performance) {
|
|
4150
|
-
contextRef.current.__performance.droppedFrames = 0;
|
|
4151
|
-
contextRef.current.__performance.minFrameTime = Infinity;
|
|
4152
|
-
contextRef.current.__performance.maxFrameTime = 0;
|
|
4153
|
-
}
|
|
4154
|
-
}
|
|
4155
|
-
};
|
|
4156
|
-
};
|
|
4157
3842
|
return {
|
|
4158
3843
|
context: {
|
|
4159
3844
|
context: contextRef.current,
|
|
@@ -4165,8 +3850,6 @@ function useKlint() {
|
|
|
4165
3850
|
KlintKeyboard,
|
|
4166
3851
|
KlintWindow,
|
|
4167
3852
|
KlintImage,
|
|
4168
|
-
KlintTimeline,
|
|
4169
|
-
KlintPerformance,
|
|
4170
3853
|
togglePlay,
|
|
4171
3854
|
useDev
|
|
4172
3855
|
};
|
|
@@ -4221,11 +3904,12 @@ export {
|
|
|
4221
3904
|
KlintCoreFunctions,
|
|
4222
3905
|
KlintFunctions,
|
|
4223
3906
|
Noise_default as Noise,
|
|
4224
|
-
|
|
4225
|
-
|
|
3907
|
+
Pixels,
|
|
3908
|
+
Quadtree_default as Quadtree,
|
|
3909
|
+
Rectangle,
|
|
4226
3910
|
Strip_default as Strip,
|
|
4227
3911
|
Text_default as Text,
|
|
4228
|
-
|
|
3912
|
+
Timeline,
|
|
4229
3913
|
Vector_default as Vector,
|
|
4230
3914
|
useKlint,
|
|
4231
3915
|
useProps,
|