@almadar/ui 5.42.0 → 5.43.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/dist/avl/index.cjs +317 -119
- package/dist/avl/index.js +317 -119
- package/dist/components/game/organisms/physics-sim/SimulationCanvas.d.ts +8 -2
- package/dist/components/index.cjs +317 -119
- package/dist/components/index.js +317 -119
- package/dist/hooks/index.cjs +68 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +68 -1
- package/dist/hooks/useRenderInterpolation.d.ts +33 -0
- package/dist/providers/index.cjs +317 -119
- package/dist/providers/index.js +317 -119
- package/dist/runtime/index.cjs +317 -119
- package/dist/runtime/index.js +317 -119
- package/package.json +1 -1
package/dist/providers/index.js
CHANGED
|
@@ -28563,6 +28563,78 @@ var init_GameOverScreen = __esm({
|
|
|
28563
28563
|
GameOverScreen.displayName = "GameOverScreen";
|
|
28564
28564
|
}
|
|
28565
28565
|
});
|
|
28566
|
+
function useRenderInterpolation(options = {}) {
|
|
28567
|
+
const tickIntervalMs = options.tickIntervalMs ?? 1e3 / 30;
|
|
28568
|
+
const prevRef = useRef(null);
|
|
28569
|
+
const currRef = useRef(null);
|
|
28570
|
+
const rafRef = useRef(null);
|
|
28571
|
+
const onSnapshot = useCallback((entities) => {
|
|
28572
|
+
prevRef.current = currRef.current;
|
|
28573
|
+
currRef.current = { entities, arrivedAt: performance.now() };
|
|
28574
|
+
}, []);
|
|
28575
|
+
const getInterpolated = useCallback((now) => {
|
|
28576
|
+
const out = /* @__PURE__ */ new Map();
|
|
28577
|
+
const curr = currRef.current;
|
|
28578
|
+
if (!curr) return out;
|
|
28579
|
+
const prev = prevRef.current;
|
|
28580
|
+
if (!prev) {
|
|
28581
|
+
for (const e of curr.entities) out.set(e.id, { x: e.x, y: e.y });
|
|
28582
|
+
return out;
|
|
28583
|
+
}
|
|
28584
|
+
const rawAlpha = (now - curr.arrivedAt) / tickIntervalMs;
|
|
28585
|
+
const alpha = rawAlpha < 0 ? 0 : rawAlpha > 1 ? 1 : rawAlpha;
|
|
28586
|
+
const prevMap = /* @__PURE__ */ new Map();
|
|
28587
|
+
for (const e of prev.entities) prevMap.set(e.id, e);
|
|
28588
|
+
for (const c of curr.entities) {
|
|
28589
|
+
const p2 = prevMap.get(c.id);
|
|
28590
|
+
if (!p2) {
|
|
28591
|
+
out.set(c.id, { x: c.x, y: c.y });
|
|
28592
|
+
} else {
|
|
28593
|
+
out.set(c.id, {
|
|
28594
|
+
x: p2.x + (c.x - p2.x) * alpha,
|
|
28595
|
+
y: p2.y + (c.y - p2.y) * alpha
|
|
28596
|
+
});
|
|
28597
|
+
}
|
|
28598
|
+
}
|
|
28599
|
+
return out;
|
|
28600
|
+
}, [tickIntervalMs]);
|
|
28601
|
+
const startLoop = useCallback(
|
|
28602
|
+
(draw) => {
|
|
28603
|
+
let active = true;
|
|
28604
|
+
const loop = () => {
|
|
28605
|
+
if (!active) return;
|
|
28606
|
+
try {
|
|
28607
|
+
draw(getInterpolated(performance.now()));
|
|
28608
|
+
} catch {
|
|
28609
|
+
}
|
|
28610
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28611
|
+
};
|
|
28612
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28613
|
+
return () => {
|
|
28614
|
+
active = false;
|
|
28615
|
+
if (rafRef.current !== null) {
|
|
28616
|
+
cancelAnimationFrame(rafRef.current);
|
|
28617
|
+
rafRef.current = null;
|
|
28618
|
+
}
|
|
28619
|
+
};
|
|
28620
|
+
},
|
|
28621
|
+
[getInterpolated]
|
|
28622
|
+
);
|
|
28623
|
+
useEffect(() => {
|
|
28624
|
+
return () => {
|
|
28625
|
+
if (rafRef.current !== null) {
|
|
28626
|
+
cancelAnimationFrame(rafRef.current);
|
|
28627
|
+
rafRef.current = null;
|
|
28628
|
+
}
|
|
28629
|
+
};
|
|
28630
|
+
}, []);
|
|
28631
|
+
return { onSnapshot, getInterpolated, startLoop };
|
|
28632
|
+
}
|
|
28633
|
+
var init_useRenderInterpolation = __esm({
|
|
28634
|
+
"hooks/useRenderInterpolation.ts"() {
|
|
28635
|
+
"use client";
|
|
28636
|
+
}
|
|
28637
|
+
});
|
|
28566
28638
|
function PlatformerCanvas({
|
|
28567
28639
|
player,
|
|
28568
28640
|
platforms = [
|
|
@@ -28631,8 +28703,43 @@ function PlatformerCanvas({
|
|
|
28631
28703
|
y: 336,
|
|
28632
28704
|
width: 32,
|
|
28633
28705
|
height: 48,
|
|
28706
|
+
vx: 0,
|
|
28707
|
+
vy: 0,
|
|
28708
|
+
grounded: true,
|
|
28634
28709
|
facingRight: true
|
|
28635
28710
|
};
|
|
28711
|
+
const playerRef = useRef(resolvedPlayer);
|
|
28712
|
+
playerRef.current = resolvedPlayer;
|
|
28713
|
+
const interp = useRenderInterpolation();
|
|
28714
|
+
useEffect(() => {
|
|
28715
|
+
interp.onSnapshot([{ id: "player", x: resolvedPlayer.x, y: resolvedPlayer.y }]);
|
|
28716
|
+
}, [resolvedPlayer.x, resolvedPlayer.y]);
|
|
28717
|
+
const propsRef = useRef({
|
|
28718
|
+
platforms,
|
|
28719
|
+
worldWidth,
|
|
28720
|
+
worldHeight,
|
|
28721
|
+
canvasWidth,
|
|
28722
|
+
canvasHeight,
|
|
28723
|
+
followCamera,
|
|
28724
|
+
bgColor,
|
|
28725
|
+
playerSprite,
|
|
28726
|
+
tileSprites,
|
|
28727
|
+
backgroundImage,
|
|
28728
|
+
assetBaseUrl
|
|
28729
|
+
});
|
|
28730
|
+
propsRef.current = {
|
|
28731
|
+
platforms,
|
|
28732
|
+
worldWidth,
|
|
28733
|
+
worldHeight,
|
|
28734
|
+
canvasWidth,
|
|
28735
|
+
canvasHeight,
|
|
28736
|
+
followCamera,
|
|
28737
|
+
bgColor,
|
|
28738
|
+
playerSprite,
|
|
28739
|
+
tileSprites,
|
|
28740
|
+
backgroundImage,
|
|
28741
|
+
assetBaseUrl
|
|
28742
|
+
};
|
|
28636
28743
|
const handleKeyDown = useCallback((e) => {
|
|
28637
28744
|
if (keysRef.current.has(e.code)) return;
|
|
28638
28745
|
keysRef.current.add(e.code);
|
|
@@ -28681,124 +28788,149 @@ function PlatformerCanvas({
|
|
|
28681
28788
|
canvas.width = canvasWidth * dpr;
|
|
28682
28789
|
canvas.height = canvasHeight * dpr;
|
|
28683
28790
|
ctx.scale(dpr, dpr);
|
|
28684
|
-
|
|
28685
|
-
|
|
28686
|
-
|
|
28687
|
-
|
|
28688
|
-
|
|
28689
|
-
|
|
28690
|
-
|
|
28691
|
-
|
|
28692
|
-
|
|
28693
|
-
|
|
28694
|
-
|
|
28695
|
-
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
28699
|
-
|
|
28700
|
-
|
|
28701
|
-
|
|
28702
|
-
|
|
28703
|
-
|
|
28704
|
-
|
|
28705
|
-
|
|
28706
|
-
|
|
28707
|
-
|
|
28708
|
-
|
|
28709
|
-
|
|
28710
|
-
|
|
28711
|
-
|
|
28712
|
-
|
|
28713
|
-
|
|
28714
|
-
|
|
28715
|
-
|
|
28716
|
-
|
|
28717
|
-
|
|
28718
|
-
|
|
28719
|
-
const px = plat.x - camX;
|
|
28720
|
-
const py = plat.y - camY;
|
|
28721
|
-
const platType = plat.type ?? "ground";
|
|
28722
|
-
const spriteUrl = tileSprites?.[platType];
|
|
28723
|
-
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
28724
|
-
if (tileImg) {
|
|
28725
|
-
const tileW = tileImg.naturalWidth;
|
|
28726
|
-
const tileH = tileImg.naturalHeight;
|
|
28727
|
-
const scaleH = plat.height / tileH;
|
|
28728
|
-
const scaledW = tileW * scaleH;
|
|
28729
|
-
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
28730
|
-
const drawW = Math.min(scaledW, plat.width - tx);
|
|
28731
|
-
const srcW = drawW / scaleH;
|
|
28732
|
-
ctx.drawImage(tileImg, 0, 0, srcW, tileH, px + tx, py, drawW, plat.height);
|
|
28733
|
-
}
|
|
28791
|
+
}, [canvasWidth, canvasHeight]);
|
|
28792
|
+
useEffect(() => {
|
|
28793
|
+
const drawFrame = (positions) => {
|
|
28794
|
+
const canvas = canvasRef.current;
|
|
28795
|
+
if (!canvas) return;
|
|
28796
|
+
const ctx = canvas.getContext("2d");
|
|
28797
|
+
if (!ctx) return;
|
|
28798
|
+
const {
|
|
28799
|
+
platforms: plats,
|
|
28800
|
+
worldWidth: ww,
|
|
28801
|
+
worldHeight: wh,
|
|
28802
|
+
canvasWidth: cw,
|
|
28803
|
+
canvasHeight: ch,
|
|
28804
|
+
followCamera: fc,
|
|
28805
|
+
bgColor: bg,
|
|
28806
|
+
playerSprite: pSprite,
|
|
28807
|
+
tileSprites: tSprites,
|
|
28808
|
+
backgroundImage: bgImg
|
|
28809
|
+
} = propsRef.current;
|
|
28810
|
+
const auth = playerRef.current;
|
|
28811
|
+
const interped = positions.get("player");
|
|
28812
|
+
const px = interped?.x ?? auth.x;
|
|
28813
|
+
const py = interped?.y ?? auth.y;
|
|
28814
|
+
let camX = 0;
|
|
28815
|
+
let camY = 0;
|
|
28816
|
+
if (fc) {
|
|
28817
|
+
camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
|
|
28818
|
+
camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
|
|
28819
|
+
}
|
|
28820
|
+
const bgImage = bgImg ? loadImage(bgImg) : null;
|
|
28821
|
+
if (bgImage) {
|
|
28822
|
+
ctx.drawImage(bgImage, 0, 0, cw, ch);
|
|
28823
|
+
} else if (bg) {
|
|
28824
|
+
ctx.fillStyle = bg;
|
|
28825
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
28734
28826
|
} else {
|
|
28735
|
-
const
|
|
28736
|
-
|
|
28737
|
-
|
|
28738
|
-
ctx.fillStyle =
|
|
28739
|
-
ctx.fillRect(
|
|
28740
|
-
|
|
28741
|
-
|
|
28742
|
-
|
|
28743
|
-
|
|
28744
|
-
|
|
28745
|
-
|
|
28827
|
+
const grad = ctx.createLinearGradient(0, 0, 0, ch);
|
|
28828
|
+
grad.addColorStop(0, SKY_GRADIENT_TOP);
|
|
28829
|
+
grad.addColorStop(1, SKY_GRADIENT_BOTTOM);
|
|
28830
|
+
ctx.fillStyle = grad;
|
|
28831
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
28832
|
+
}
|
|
28833
|
+
ctx.strokeStyle = GRID_COLOR;
|
|
28834
|
+
ctx.lineWidth = 1;
|
|
28835
|
+
const gridSize = 32;
|
|
28836
|
+
for (let gx = -camX % gridSize; gx < cw; gx += gridSize) {
|
|
28837
|
+
ctx.beginPath();
|
|
28838
|
+
ctx.moveTo(gx, 0);
|
|
28839
|
+
ctx.lineTo(gx, ch);
|
|
28840
|
+
ctx.stroke();
|
|
28841
|
+
}
|
|
28842
|
+
for (let gy = -camY % gridSize; gy < ch; gy += gridSize) {
|
|
28843
|
+
ctx.beginPath();
|
|
28844
|
+
ctx.moveTo(0, gy);
|
|
28845
|
+
ctx.lineTo(cw, gy);
|
|
28846
|
+
ctx.stroke();
|
|
28847
|
+
}
|
|
28848
|
+
for (const plat of plats) {
|
|
28849
|
+
const platX = plat.x - camX;
|
|
28850
|
+
const platY = plat.y - camY;
|
|
28851
|
+
const platType = plat.type ?? "ground";
|
|
28852
|
+
const spriteUrl = tSprites?.[platType];
|
|
28853
|
+
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
28854
|
+
if (tileImg) {
|
|
28855
|
+
const tileW = tileImg.naturalWidth;
|
|
28856
|
+
const tileH = tileImg.naturalHeight;
|
|
28857
|
+
const scaleH = plat.height / tileH;
|
|
28858
|
+
const scaledW = tileW * scaleH;
|
|
28859
|
+
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
28860
|
+
const drawW = Math.min(scaledW, plat.width - tx);
|
|
28861
|
+
const srcW = drawW / scaleH;
|
|
28862
|
+
ctx.drawImage(tileImg, 0, 0, srcW, tileH, platX + tx, platY, drawW, plat.height);
|
|
28863
|
+
}
|
|
28864
|
+
} else {
|
|
28865
|
+
const color = PLATFORM_COLORS[platType] ?? PLATFORM_COLORS.ground;
|
|
28866
|
+
ctx.fillStyle = color;
|
|
28867
|
+
ctx.fillRect(platX, platY, plat.width, plat.height);
|
|
28868
|
+
ctx.fillStyle = "rgba(255, 255, 255, 0.15)";
|
|
28869
|
+
ctx.fillRect(platX, platY, plat.width, 3);
|
|
28870
|
+
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
|
|
28871
|
+
ctx.fillRect(platX, platY + plat.height - 2, plat.width, 2);
|
|
28872
|
+
if (platType === "hazard") {
|
|
28873
|
+
ctx.strokeStyle = "#e74c3c";
|
|
28874
|
+
ctx.lineWidth = 2;
|
|
28875
|
+
for (let sx = platX; sx < platX + plat.width; sx += 12) {
|
|
28876
|
+
ctx.beginPath();
|
|
28877
|
+
ctx.moveTo(sx, platY);
|
|
28878
|
+
ctx.lineTo(sx + 6, platY + plat.height);
|
|
28879
|
+
ctx.stroke();
|
|
28880
|
+
}
|
|
28881
|
+
}
|
|
28882
|
+
if (platType === "goal") {
|
|
28883
|
+
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
28746
28884
|
ctx.beginPath();
|
|
28747
|
-
ctx.
|
|
28748
|
-
ctx.
|
|
28749
|
-
ctx.stroke();
|
|
28885
|
+
ctx.arc(platX + plat.width / 2, platY - 10, 8, 0, Math.PI * 2);
|
|
28886
|
+
ctx.fill();
|
|
28750
28887
|
}
|
|
28751
28888
|
}
|
|
28752
|
-
if (platType === "goal") {
|
|
28753
|
-
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
28754
|
-
ctx.beginPath();
|
|
28755
|
-
ctx.arc(px + plat.width / 2, py - 10, 8, 0, Math.PI * 2);
|
|
28756
|
-
ctx.fill();
|
|
28757
|
-
}
|
|
28758
28889
|
}
|
|
28759
|
-
|
|
28760
|
-
|
|
28761
|
-
|
|
28762
|
-
|
|
28763
|
-
|
|
28764
|
-
|
|
28765
|
-
|
|
28766
|
-
|
|
28767
|
-
|
|
28768
|
-
|
|
28769
|
-
|
|
28770
|
-
|
|
28771
|
-
|
|
28890
|
+
const pw = auth.width ?? 24;
|
|
28891
|
+
const ph = auth.height ?? 32;
|
|
28892
|
+
const ppx = px - camX;
|
|
28893
|
+
const ppy = py - camY;
|
|
28894
|
+
const facingRight = auth.facingRight ?? true;
|
|
28895
|
+
const playerImg = pSprite ? loadImage(pSprite) : null;
|
|
28896
|
+
if (playerImg) {
|
|
28897
|
+
ctx.save();
|
|
28898
|
+
if (!facingRight) {
|
|
28899
|
+
ctx.translate(ppx + pw, ppy);
|
|
28900
|
+
ctx.scale(-1, 1);
|
|
28901
|
+
ctx.drawImage(playerImg, 0, 0, pw, ph);
|
|
28902
|
+
} else {
|
|
28903
|
+
ctx.drawImage(playerImg, ppx, ppy, pw, ph);
|
|
28904
|
+
}
|
|
28905
|
+
ctx.restore();
|
|
28772
28906
|
} else {
|
|
28773
|
-
ctx.
|
|
28907
|
+
ctx.fillStyle = PLAYER_COLOR;
|
|
28908
|
+
const radius = Math.min(pw, ph) * 0.25;
|
|
28909
|
+
ctx.beginPath();
|
|
28910
|
+
ctx.moveTo(ppx + radius, ppy);
|
|
28911
|
+
ctx.lineTo(ppx + pw - radius, ppy);
|
|
28912
|
+
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
28913
|
+
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
28914
|
+
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
28915
|
+
ctx.lineTo(ppx + radius, ppy + ph);
|
|
28916
|
+
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
28917
|
+
ctx.lineTo(ppx, ppy + radius);
|
|
28918
|
+
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
28919
|
+
ctx.fill();
|
|
28920
|
+
const eyeY = ppy + ph * 0.3;
|
|
28921
|
+
const eyeSize = 3;
|
|
28922
|
+
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
28923
|
+
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
28924
|
+
ctx.beginPath();
|
|
28925
|
+
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28926
|
+
ctx.fill();
|
|
28927
|
+
ctx.beginPath();
|
|
28928
|
+
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28929
|
+
ctx.fill();
|
|
28774
28930
|
}
|
|
28775
|
-
|
|
28776
|
-
|
|
28777
|
-
|
|
28778
|
-
const radius = Math.min(pw, ph) * 0.25;
|
|
28779
|
-
ctx.beginPath();
|
|
28780
|
-
ctx.moveTo(ppx + radius, ppy);
|
|
28781
|
-
ctx.lineTo(ppx + pw - radius, ppy);
|
|
28782
|
-
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
28783
|
-
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
28784
|
-
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
28785
|
-
ctx.lineTo(ppx + radius, ppy + ph);
|
|
28786
|
-
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
28787
|
-
ctx.lineTo(ppx, ppy + radius);
|
|
28788
|
-
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
28789
|
-
ctx.fill();
|
|
28790
|
-
const eyeY = ppy + ph * 0.3;
|
|
28791
|
-
const eyeSize = 3;
|
|
28792
|
-
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
28793
|
-
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
28794
|
-
ctx.beginPath();
|
|
28795
|
-
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28796
|
-
ctx.fill();
|
|
28797
|
-
ctx.beginPath();
|
|
28798
|
-
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28799
|
-
ctx.fill();
|
|
28800
|
-
}
|
|
28801
|
-
}, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
|
|
28931
|
+
};
|
|
28932
|
+
return interp.startLoop(drawFrame);
|
|
28933
|
+
}, [interp.startLoop, loadImage]);
|
|
28802
28934
|
return /* @__PURE__ */ jsx(
|
|
28803
28935
|
"canvas",
|
|
28804
28936
|
{
|
|
@@ -28816,6 +28948,7 @@ var init_PlatformerCanvas = __esm({
|
|
|
28816
28948
|
init_cn();
|
|
28817
28949
|
init_useEventBus();
|
|
28818
28950
|
init_verificationRegistry();
|
|
28951
|
+
init_useRenderInterpolation();
|
|
28819
28952
|
PLATFORM_COLORS = {
|
|
28820
28953
|
ground: "#4a7c59",
|
|
28821
28954
|
platform: "#7c6b4a",
|
|
@@ -29198,13 +29331,13 @@ var init_MapView = __esm({
|
|
|
29198
29331
|
shadowSize: [41, 41]
|
|
29199
29332
|
});
|
|
29200
29333
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
29201
|
-
const { useEffect:
|
|
29334
|
+
const { useEffect: useEffect74, useRef: useRef69, useCallback: useCallback112, useState: useState104 } = React83__default;
|
|
29202
29335
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
29203
29336
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
29204
29337
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
29205
29338
|
const map = useMap();
|
|
29206
|
-
const prevRef =
|
|
29207
|
-
|
|
29339
|
+
const prevRef = useRef69({ centerLat, centerLng, zoom });
|
|
29340
|
+
useEffect74(() => {
|
|
29208
29341
|
const prev = prevRef.current;
|
|
29209
29342
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
29210
29343
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -29215,7 +29348,7 @@ var init_MapView = __esm({
|
|
|
29215
29348
|
}
|
|
29216
29349
|
function MapClickHandler({ onMapClick }) {
|
|
29217
29350
|
const map = useMap();
|
|
29218
|
-
|
|
29351
|
+
useEffect74(() => {
|
|
29219
29352
|
if (!onMapClick) return;
|
|
29220
29353
|
const handler = (e) => {
|
|
29221
29354
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -29244,7 +29377,7 @@ var init_MapView = __esm({
|
|
|
29244
29377
|
}) {
|
|
29245
29378
|
const eventBus = useEventBus2();
|
|
29246
29379
|
const [clickedPosition, setClickedPosition] = useState104(null);
|
|
29247
|
-
const handleMapClick =
|
|
29380
|
+
const handleMapClick = useCallback112((lat, lng) => {
|
|
29248
29381
|
if (showClickedPin) {
|
|
29249
29382
|
setClickedPosition({ lat, lng });
|
|
29250
29383
|
}
|
|
@@ -29253,7 +29386,7 @@ var init_MapView = __esm({
|
|
|
29253
29386
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
29254
29387
|
}
|
|
29255
29388
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
29256
|
-
const handleMarkerClick =
|
|
29389
|
+
const handleMarkerClick = useCallback112((marker) => {
|
|
29257
29390
|
onMarkerClick?.(marker);
|
|
29258
29391
|
if (markerClickEvent) {
|
|
29259
29392
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -45106,11 +45239,13 @@ function SimulationCanvas({
|
|
|
45106
45239
|
height = 400,
|
|
45107
45240
|
running,
|
|
45108
45241
|
speed = 1,
|
|
45242
|
+
bodies: externalBodies,
|
|
45109
45243
|
className
|
|
45110
45244
|
}) {
|
|
45111
45245
|
const preset = useMemo(() => resolvePreset(presetProp), [presetProp]);
|
|
45112
45246
|
const canvasRef = useRef(null);
|
|
45113
45247
|
const bodiesRef = useRef(structuredClone(preset.bodies));
|
|
45248
|
+
const interp = useRenderInterpolation();
|
|
45114
45249
|
useEffect(() => {
|
|
45115
45250
|
bodiesRef.current = structuredClone(preset.bodies);
|
|
45116
45251
|
}, [preset]);
|
|
@@ -45208,6 +45343,67 @@ function SimulationCanvas({
|
|
|
45208
45343
|
}
|
|
45209
45344
|
}, [width, height, preset]);
|
|
45210
45345
|
useEffect(() => {
|
|
45346
|
+
if (!externalBodies) return;
|
|
45347
|
+
interp.onSnapshot(externalBodies.map((b) => ({ id: b.id, x: b.x, y: b.y })));
|
|
45348
|
+
}, [externalBodies]);
|
|
45349
|
+
const presetRef = useRef(preset);
|
|
45350
|
+
presetRef.current = preset;
|
|
45351
|
+
const widthRef = useRef(width);
|
|
45352
|
+
widthRef.current = width;
|
|
45353
|
+
const heightRef = useRef(height);
|
|
45354
|
+
heightRef.current = height;
|
|
45355
|
+
useEffect(() => {
|
|
45356
|
+
if (!externalBodies) return;
|
|
45357
|
+
const drawInterpolated = (positions) => {
|
|
45358
|
+
const canvas = canvasRef.current;
|
|
45359
|
+
if (!canvas) return;
|
|
45360
|
+
const ctx = canvas.getContext("2d");
|
|
45361
|
+
if (!ctx) return;
|
|
45362
|
+
const bodies = bodiesRef.current;
|
|
45363
|
+
const p2 = presetRef.current;
|
|
45364
|
+
const w = widthRef.current;
|
|
45365
|
+
const h = heightRef.current;
|
|
45366
|
+
ctx.clearRect(0, 0, w, h);
|
|
45367
|
+
ctx.fillStyle = p2.backgroundColor ?? "#1a1a2e";
|
|
45368
|
+
ctx.fillRect(0, 0, w, h);
|
|
45369
|
+
if (p2.constraints) {
|
|
45370
|
+
for (const c of p2.constraints) {
|
|
45371
|
+
const a = bodies[c.bodyA];
|
|
45372
|
+
const b = bodies[c.bodyB];
|
|
45373
|
+
if (a && b) {
|
|
45374
|
+
const aPos = positions.get(a.id) ?? a;
|
|
45375
|
+
const bPos = positions.get(b.id) ?? b;
|
|
45376
|
+
ctx.beginPath();
|
|
45377
|
+
ctx.moveTo(aPos.x, aPos.y);
|
|
45378
|
+
ctx.lineTo(bPos.x, bPos.y);
|
|
45379
|
+
ctx.strokeStyle = "#533483";
|
|
45380
|
+
ctx.lineWidth = 1;
|
|
45381
|
+
ctx.setLineDash([4, 4]);
|
|
45382
|
+
ctx.stroke();
|
|
45383
|
+
ctx.setLineDash([]);
|
|
45384
|
+
}
|
|
45385
|
+
}
|
|
45386
|
+
}
|
|
45387
|
+
for (const body of bodies) {
|
|
45388
|
+
const pos = positions.get(body.id) ?? body;
|
|
45389
|
+
ctx.beginPath();
|
|
45390
|
+
ctx.arc(pos.x, pos.y, body.radius, 0, Math.PI * 2);
|
|
45391
|
+
ctx.fillStyle = body.color ?? "#e94560";
|
|
45392
|
+
ctx.fill();
|
|
45393
|
+
if (p2.showVelocity) {
|
|
45394
|
+
ctx.beginPath();
|
|
45395
|
+
ctx.moveTo(pos.x, pos.y);
|
|
45396
|
+
ctx.lineTo(pos.x + body.vx * 0.1, pos.y + body.vy * 0.1);
|
|
45397
|
+
ctx.strokeStyle = "#16213e";
|
|
45398
|
+
ctx.lineWidth = 2;
|
|
45399
|
+
ctx.stroke();
|
|
45400
|
+
}
|
|
45401
|
+
}
|
|
45402
|
+
};
|
|
45403
|
+
return interp.startLoop(drawInterpolated);
|
|
45404
|
+
}, [externalBodies !== void 0, interp.startLoop]);
|
|
45405
|
+
useEffect(() => {
|
|
45406
|
+
if (externalBodies !== void 0) return;
|
|
45211
45407
|
if (!running) return;
|
|
45212
45408
|
let raf;
|
|
45213
45409
|
const loop = () => {
|
|
@@ -45217,10 +45413,11 @@ function SimulationCanvas({
|
|
|
45217
45413
|
};
|
|
45218
45414
|
raf = requestAnimationFrame(loop);
|
|
45219
45415
|
return () => cancelAnimationFrame(raf);
|
|
45220
|
-
}, [running, step, draw]);
|
|
45416
|
+
}, [running, step, draw, externalBodies]);
|
|
45221
45417
|
useEffect(() => {
|
|
45418
|
+
if (externalBodies !== void 0) return;
|
|
45222
45419
|
draw();
|
|
45223
|
-
}, [draw]);
|
|
45420
|
+
}, [draw, externalBodies]);
|
|
45224
45421
|
useEffect(() => {
|
|
45225
45422
|
if (typeof window === "undefined") return;
|
|
45226
45423
|
const canvas = canvasRef.current;
|
|
@@ -45246,6 +45443,7 @@ var init_SimulationCanvas = __esm({
|
|
|
45246
45443
|
init_atoms2();
|
|
45247
45444
|
init_verificationRegistry();
|
|
45248
45445
|
init_presets();
|
|
45446
|
+
init_useRenderInterpolation();
|
|
45249
45447
|
SimulationCanvas.displayName = "SimulationCanvas";
|
|
45250
45448
|
}
|
|
45251
45449
|
});
|