@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/runtime/index.cjs
CHANGED
|
@@ -28176,6 +28176,78 @@ var init_GameOverScreen = __esm({
|
|
|
28176
28176
|
GameOverScreen.displayName = "GameOverScreen";
|
|
28177
28177
|
}
|
|
28178
28178
|
});
|
|
28179
|
+
function useRenderInterpolation(options = {}) {
|
|
28180
|
+
const tickIntervalMs = options.tickIntervalMs ?? 1e3 / 30;
|
|
28181
|
+
const prevRef = React82.useRef(null);
|
|
28182
|
+
const currRef = React82.useRef(null);
|
|
28183
|
+
const rafRef = React82.useRef(null);
|
|
28184
|
+
const onSnapshot = React82.useCallback((entities) => {
|
|
28185
|
+
prevRef.current = currRef.current;
|
|
28186
|
+
currRef.current = { entities, arrivedAt: performance.now() };
|
|
28187
|
+
}, []);
|
|
28188
|
+
const getInterpolated = React82.useCallback((now2) => {
|
|
28189
|
+
const out = /* @__PURE__ */ new Map();
|
|
28190
|
+
const curr = currRef.current;
|
|
28191
|
+
if (!curr) return out;
|
|
28192
|
+
const prev = prevRef.current;
|
|
28193
|
+
if (!prev) {
|
|
28194
|
+
for (const e of curr.entities) out.set(e.id, { x: e.x, y: e.y });
|
|
28195
|
+
return out;
|
|
28196
|
+
}
|
|
28197
|
+
const rawAlpha = (now2 - curr.arrivedAt) / tickIntervalMs;
|
|
28198
|
+
const alpha = rawAlpha < 0 ? 0 : rawAlpha > 1 ? 1 : rawAlpha;
|
|
28199
|
+
const prevMap = /* @__PURE__ */ new Map();
|
|
28200
|
+
for (const e of prev.entities) prevMap.set(e.id, e);
|
|
28201
|
+
for (const c of curr.entities) {
|
|
28202
|
+
const p2 = prevMap.get(c.id);
|
|
28203
|
+
if (!p2) {
|
|
28204
|
+
out.set(c.id, { x: c.x, y: c.y });
|
|
28205
|
+
} else {
|
|
28206
|
+
out.set(c.id, {
|
|
28207
|
+
x: p2.x + (c.x - p2.x) * alpha,
|
|
28208
|
+
y: p2.y + (c.y - p2.y) * alpha
|
|
28209
|
+
});
|
|
28210
|
+
}
|
|
28211
|
+
}
|
|
28212
|
+
return out;
|
|
28213
|
+
}, [tickIntervalMs]);
|
|
28214
|
+
const startLoop = React82.useCallback(
|
|
28215
|
+
(draw) => {
|
|
28216
|
+
let active = true;
|
|
28217
|
+
const loop = () => {
|
|
28218
|
+
if (!active) return;
|
|
28219
|
+
try {
|
|
28220
|
+
draw(getInterpolated(performance.now()));
|
|
28221
|
+
} catch {
|
|
28222
|
+
}
|
|
28223
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28224
|
+
};
|
|
28225
|
+
rafRef.current = requestAnimationFrame(loop);
|
|
28226
|
+
return () => {
|
|
28227
|
+
active = false;
|
|
28228
|
+
if (rafRef.current !== null) {
|
|
28229
|
+
cancelAnimationFrame(rafRef.current);
|
|
28230
|
+
rafRef.current = null;
|
|
28231
|
+
}
|
|
28232
|
+
};
|
|
28233
|
+
},
|
|
28234
|
+
[getInterpolated]
|
|
28235
|
+
);
|
|
28236
|
+
React82.useEffect(() => {
|
|
28237
|
+
return () => {
|
|
28238
|
+
if (rafRef.current !== null) {
|
|
28239
|
+
cancelAnimationFrame(rafRef.current);
|
|
28240
|
+
rafRef.current = null;
|
|
28241
|
+
}
|
|
28242
|
+
};
|
|
28243
|
+
}, []);
|
|
28244
|
+
return { onSnapshot, getInterpolated, startLoop };
|
|
28245
|
+
}
|
|
28246
|
+
var init_useRenderInterpolation = __esm({
|
|
28247
|
+
"hooks/useRenderInterpolation.ts"() {
|
|
28248
|
+
"use client";
|
|
28249
|
+
}
|
|
28250
|
+
});
|
|
28179
28251
|
function PlatformerCanvas({
|
|
28180
28252
|
player,
|
|
28181
28253
|
platforms = [
|
|
@@ -28244,8 +28316,43 @@ function PlatformerCanvas({
|
|
|
28244
28316
|
y: 336,
|
|
28245
28317
|
width: 32,
|
|
28246
28318
|
height: 48,
|
|
28319
|
+
vx: 0,
|
|
28320
|
+
vy: 0,
|
|
28321
|
+
grounded: true,
|
|
28247
28322
|
facingRight: true
|
|
28248
28323
|
};
|
|
28324
|
+
const playerRef = React82.useRef(resolvedPlayer);
|
|
28325
|
+
playerRef.current = resolvedPlayer;
|
|
28326
|
+
const interp = useRenderInterpolation();
|
|
28327
|
+
React82.useEffect(() => {
|
|
28328
|
+
interp.onSnapshot([{ id: "player", x: resolvedPlayer.x, y: resolvedPlayer.y }]);
|
|
28329
|
+
}, [resolvedPlayer.x, resolvedPlayer.y]);
|
|
28330
|
+
const propsRef = React82.useRef({
|
|
28331
|
+
platforms,
|
|
28332
|
+
worldWidth,
|
|
28333
|
+
worldHeight,
|
|
28334
|
+
canvasWidth,
|
|
28335
|
+
canvasHeight,
|
|
28336
|
+
followCamera,
|
|
28337
|
+
bgColor,
|
|
28338
|
+
playerSprite,
|
|
28339
|
+
tileSprites,
|
|
28340
|
+
backgroundImage,
|
|
28341
|
+
assetBaseUrl
|
|
28342
|
+
});
|
|
28343
|
+
propsRef.current = {
|
|
28344
|
+
platforms,
|
|
28345
|
+
worldWidth,
|
|
28346
|
+
worldHeight,
|
|
28347
|
+
canvasWidth,
|
|
28348
|
+
canvasHeight,
|
|
28349
|
+
followCamera,
|
|
28350
|
+
bgColor,
|
|
28351
|
+
playerSprite,
|
|
28352
|
+
tileSprites,
|
|
28353
|
+
backgroundImage,
|
|
28354
|
+
assetBaseUrl
|
|
28355
|
+
};
|
|
28249
28356
|
const handleKeyDown = React82.useCallback((e) => {
|
|
28250
28357
|
if (keysRef.current.has(e.code)) return;
|
|
28251
28358
|
keysRef.current.add(e.code);
|
|
@@ -28294,124 +28401,149 @@ function PlatformerCanvas({
|
|
|
28294
28401
|
canvas.width = canvasWidth * dpr;
|
|
28295
28402
|
canvas.height = canvasHeight * dpr;
|
|
28296
28403
|
ctx.scale(dpr, dpr);
|
|
28297
|
-
|
|
28298
|
-
|
|
28299
|
-
|
|
28300
|
-
|
|
28301
|
-
|
|
28302
|
-
|
|
28303
|
-
|
|
28304
|
-
|
|
28305
|
-
|
|
28306
|
-
|
|
28307
|
-
|
|
28308
|
-
|
|
28309
|
-
|
|
28310
|
-
|
|
28311
|
-
|
|
28312
|
-
|
|
28313
|
-
|
|
28314
|
-
|
|
28315
|
-
|
|
28316
|
-
|
|
28317
|
-
|
|
28318
|
-
|
|
28319
|
-
|
|
28320
|
-
|
|
28321
|
-
|
|
28322
|
-
|
|
28323
|
-
|
|
28324
|
-
|
|
28325
|
-
|
|
28326
|
-
|
|
28327
|
-
|
|
28328
|
-
|
|
28329
|
-
|
|
28330
|
-
|
|
28331
|
-
|
|
28332
|
-
const px = plat.x - camX;
|
|
28333
|
-
const py = plat.y - camY;
|
|
28334
|
-
const platType = plat.type ?? "ground";
|
|
28335
|
-
const spriteUrl = tileSprites?.[platType];
|
|
28336
|
-
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
28337
|
-
if (tileImg) {
|
|
28338
|
-
const tileW = tileImg.naturalWidth;
|
|
28339
|
-
const tileH = tileImg.naturalHeight;
|
|
28340
|
-
const scaleH = plat.height / tileH;
|
|
28341
|
-
const scaledW = tileW * scaleH;
|
|
28342
|
-
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
28343
|
-
const drawW = Math.min(scaledW, plat.width - tx);
|
|
28344
|
-
const srcW = drawW / scaleH;
|
|
28345
|
-
ctx.drawImage(tileImg, 0, 0, srcW, tileH, px + tx, py, drawW, plat.height);
|
|
28346
|
-
}
|
|
28404
|
+
}, [canvasWidth, canvasHeight]);
|
|
28405
|
+
React82.useEffect(() => {
|
|
28406
|
+
const drawFrame = (positions) => {
|
|
28407
|
+
const canvas = canvasRef.current;
|
|
28408
|
+
if (!canvas) return;
|
|
28409
|
+
const ctx = canvas.getContext("2d");
|
|
28410
|
+
if (!ctx) return;
|
|
28411
|
+
const {
|
|
28412
|
+
platforms: plats,
|
|
28413
|
+
worldWidth: ww,
|
|
28414
|
+
worldHeight: wh,
|
|
28415
|
+
canvasWidth: cw,
|
|
28416
|
+
canvasHeight: ch,
|
|
28417
|
+
followCamera: fc,
|
|
28418
|
+
bgColor: bg,
|
|
28419
|
+
playerSprite: pSprite,
|
|
28420
|
+
tileSprites: tSprites,
|
|
28421
|
+
backgroundImage: bgImg
|
|
28422
|
+
} = propsRef.current;
|
|
28423
|
+
const auth = playerRef.current;
|
|
28424
|
+
const interped = positions.get("player");
|
|
28425
|
+
const px = interped?.x ?? auth.x;
|
|
28426
|
+
const py = interped?.y ?? auth.y;
|
|
28427
|
+
let camX = 0;
|
|
28428
|
+
let camY = 0;
|
|
28429
|
+
if (fc) {
|
|
28430
|
+
camX = Math.max(0, Math.min(px - cw / 2, ww - cw));
|
|
28431
|
+
camY = Math.max(0, Math.min(py - ch / 2 - 50, wh - ch));
|
|
28432
|
+
}
|
|
28433
|
+
const bgImage = bgImg ? loadImage(bgImg) : null;
|
|
28434
|
+
if (bgImage) {
|
|
28435
|
+
ctx.drawImage(bgImage, 0, 0, cw, ch);
|
|
28436
|
+
} else if (bg) {
|
|
28437
|
+
ctx.fillStyle = bg;
|
|
28438
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
28347
28439
|
} else {
|
|
28348
|
-
const
|
|
28349
|
-
|
|
28350
|
-
|
|
28351
|
-
ctx.fillStyle =
|
|
28352
|
-
ctx.fillRect(
|
|
28353
|
-
|
|
28354
|
-
|
|
28355
|
-
|
|
28356
|
-
|
|
28357
|
-
|
|
28358
|
-
|
|
28440
|
+
const grad = ctx.createLinearGradient(0, 0, 0, ch);
|
|
28441
|
+
grad.addColorStop(0, SKY_GRADIENT_TOP);
|
|
28442
|
+
grad.addColorStop(1, SKY_GRADIENT_BOTTOM);
|
|
28443
|
+
ctx.fillStyle = grad;
|
|
28444
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
28445
|
+
}
|
|
28446
|
+
ctx.strokeStyle = GRID_COLOR;
|
|
28447
|
+
ctx.lineWidth = 1;
|
|
28448
|
+
const gridSize = 32;
|
|
28449
|
+
for (let gx = -camX % gridSize; gx < cw; gx += gridSize) {
|
|
28450
|
+
ctx.beginPath();
|
|
28451
|
+
ctx.moveTo(gx, 0);
|
|
28452
|
+
ctx.lineTo(gx, ch);
|
|
28453
|
+
ctx.stroke();
|
|
28454
|
+
}
|
|
28455
|
+
for (let gy = -camY % gridSize; gy < ch; gy += gridSize) {
|
|
28456
|
+
ctx.beginPath();
|
|
28457
|
+
ctx.moveTo(0, gy);
|
|
28458
|
+
ctx.lineTo(cw, gy);
|
|
28459
|
+
ctx.stroke();
|
|
28460
|
+
}
|
|
28461
|
+
for (const plat of plats) {
|
|
28462
|
+
const platX = plat.x - camX;
|
|
28463
|
+
const platY = plat.y - camY;
|
|
28464
|
+
const platType = plat.type ?? "ground";
|
|
28465
|
+
const spriteUrl = tSprites?.[platType];
|
|
28466
|
+
const tileImg = spriteUrl ? loadImage(spriteUrl) : null;
|
|
28467
|
+
if (tileImg) {
|
|
28468
|
+
const tileW = tileImg.naturalWidth;
|
|
28469
|
+
const tileH = tileImg.naturalHeight;
|
|
28470
|
+
const scaleH = plat.height / tileH;
|
|
28471
|
+
const scaledW = tileW * scaleH;
|
|
28472
|
+
for (let tx = 0; tx < plat.width; tx += scaledW) {
|
|
28473
|
+
const drawW = Math.min(scaledW, plat.width - tx);
|
|
28474
|
+
const srcW = drawW / scaleH;
|
|
28475
|
+
ctx.drawImage(tileImg, 0, 0, srcW, tileH, platX + tx, platY, drawW, plat.height);
|
|
28476
|
+
}
|
|
28477
|
+
} else {
|
|
28478
|
+
const color = PLATFORM_COLORS[platType] ?? PLATFORM_COLORS.ground;
|
|
28479
|
+
ctx.fillStyle = color;
|
|
28480
|
+
ctx.fillRect(platX, platY, plat.width, plat.height);
|
|
28481
|
+
ctx.fillStyle = "rgba(255, 255, 255, 0.15)";
|
|
28482
|
+
ctx.fillRect(platX, platY, plat.width, 3);
|
|
28483
|
+
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
|
|
28484
|
+
ctx.fillRect(platX, platY + plat.height - 2, plat.width, 2);
|
|
28485
|
+
if (platType === "hazard") {
|
|
28486
|
+
ctx.strokeStyle = "#e74c3c";
|
|
28487
|
+
ctx.lineWidth = 2;
|
|
28488
|
+
for (let sx = platX; sx < platX + plat.width; sx += 12) {
|
|
28489
|
+
ctx.beginPath();
|
|
28490
|
+
ctx.moveTo(sx, platY);
|
|
28491
|
+
ctx.lineTo(sx + 6, platY + plat.height);
|
|
28492
|
+
ctx.stroke();
|
|
28493
|
+
}
|
|
28494
|
+
}
|
|
28495
|
+
if (platType === "goal") {
|
|
28496
|
+
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
28359
28497
|
ctx.beginPath();
|
|
28360
|
-
ctx.
|
|
28361
|
-
ctx.
|
|
28362
|
-
ctx.stroke();
|
|
28498
|
+
ctx.arc(platX + plat.width / 2, platY - 10, 8, 0, Math.PI * 2);
|
|
28499
|
+
ctx.fill();
|
|
28363
28500
|
}
|
|
28364
28501
|
}
|
|
28365
|
-
if (platType === "goal") {
|
|
28366
|
-
ctx.fillStyle = "rgba(241, 196, 15, 0.5)";
|
|
28367
|
-
ctx.beginPath();
|
|
28368
|
-
ctx.arc(px + plat.width / 2, py - 10, 8, 0, Math.PI * 2);
|
|
28369
|
-
ctx.fill();
|
|
28370
|
-
}
|
|
28371
28502
|
}
|
|
28372
|
-
|
|
28373
|
-
|
|
28374
|
-
|
|
28375
|
-
|
|
28376
|
-
|
|
28377
|
-
|
|
28378
|
-
|
|
28379
|
-
|
|
28380
|
-
|
|
28381
|
-
|
|
28382
|
-
|
|
28383
|
-
|
|
28384
|
-
|
|
28503
|
+
const pw = auth.width ?? 24;
|
|
28504
|
+
const ph = auth.height ?? 32;
|
|
28505
|
+
const ppx = px - camX;
|
|
28506
|
+
const ppy = py - camY;
|
|
28507
|
+
const facingRight = auth.facingRight ?? true;
|
|
28508
|
+
const playerImg = pSprite ? loadImage(pSprite) : null;
|
|
28509
|
+
if (playerImg) {
|
|
28510
|
+
ctx.save();
|
|
28511
|
+
if (!facingRight) {
|
|
28512
|
+
ctx.translate(ppx + pw, ppy);
|
|
28513
|
+
ctx.scale(-1, 1);
|
|
28514
|
+
ctx.drawImage(playerImg, 0, 0, pw, ph);
|
|
28515
|
+
} else {
|
|
28516
|
+
ctx.drawImage(playerImg, ppx, ppy, pw, ph);
|
|
28517
|
+
}
|
|
28518
|
+
ctx.restore();
|
|
28385
28519
|
} else {
|
|
28386
|
-
ctx.
|
|
28520
|
+
ctx.fillStyle = PLAYER_COLOR;
|
|
28521
|
+
const radius = Math.min(pw, ph) * 0.25;
|
|
28522
|
+
ctx.beginPath();
|
|
28523
|
+
ctx.moveTo(ppx + radius, ppy);
|
|
28524
|
+
ctx.lineTo(ppx + pw - radius, ppy);
|
|
28525
|
+
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
28526
|
+
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
28527
|
+
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
28528
|
+
ctx.lineTo(ppx + radius, ppy + ph);
|
|
28529
|
+
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
28530
|
+
ctx.lineTo(ppx, ppy + radius);
|
|
28531
|
+
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
28532
|
+
ctx.fill();
|
|
28533
|
+
const eyeY = ppy + ph * 0.3;
|
|
28534
|
+
const eyeSize = 3;
|
|
28535
|
+
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
28536
|
+
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
28537
|
+
ctx.beginPath();
|
|
28538
|
+
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28539
|
+
ctx.fill();
|
|
28540
|
+
ctx.beginPath();
|
|
28541
|
+
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28542
|
+
ctx.fill();
|
|
28387
28543
|
}
|
|
28388
|
-
|
|
28389
|
-
|
|
28390
|
-
|
|
28391
|
-
const radius = Math.min(pw, ph) * 0.25;
|
|
28392
|
-
ctx.beginPath();
|
|
28393
|
-
ctx.moveTo(ppx + radius, ppy);
|
|
28394
|
-
ctx.lineTo(ppx + pw - radius, ppy);
|
|
28395
|
-
ctx.quadraticCurveTo(ppx + pw, ppy, ppx + pw, ppy + radius);
|
|
28396
|
-
ctx.lineTo(ppx + pw, ppy + ph - radius);
|
|
28397
|
-
ctx.quadraticCurveTo(ppx + pw, ppy + ph, ppx + pw - radius, ppy + ph);
|
|
28398
|
-
ctx.lineTo(ppx + radius, ppy + ph);
|
|
28399
|
-
ctx.quadraticCurveTo(ppx, ppy + ph, ppx, ppy + ph - radius);
|
|
28400
|
-
ctx.lineTo(ppx, ppy + radius);
|
|
28401
|
-
ctx.quadraticCurveTo(ppx, ppy, ppx + radius, ppy);
|
|
28402
|
-
ctx.fill();
|
|
28403
|
-
const eyeY = ppy + ph * 0.3;
|
|
28404
|
-
const eyeSize = 3;
|
|
28405
|
-
const eyeOffsetX = facingRight ? pw * 0.55 : pw * 0.2;
|
|
28406
|
-
ctx.fillStyle = PLAYER_EYE_COLOR;
|
|
28407
|
-
ctx.beginPath();
|
|
28408
|
-
ctx.arc(ppx + eyeOffsetX, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28409
|
-
ctx.fill();
|
|
28410
|
-
ctx.beginPath();
|
|
28411
|
-
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28412
|
-
ctx.fill();
|
|
28413
|
-
}
|
|
28414
|
-
}, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
|
|
28544
|
+
};
|
|
28545
|
+
return interp.startLoop(drawFrame);
|
|
28546
|
+
}, [interp.startLoop, loadImage]);
|
|
28415
28547
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28416
28548
|
"canvas",
|
|
28417
28549
|
{
|
|
@@ -28429,6 +28561,7 @@ var init_PlatformerCanvas = __esm({
|
|
|
28429
28561
|
init_cn();
|
|
28430
28562
|
init_useEventBus();
|
|
28431
28563
|
init_verificationRegistry();
|
|
28564
|
+
init_useRenderInterpolation();
|
|
28432
28565
|
PLATFORM_COLORS = {
|
|
28433
28566
|
ground: "#4a7c59",
|
|
28434
28567
|
platform: "#7c6b4a",
|
|
@@ -28811,13 +28944,13 @@ var init_MapView = __esm({
|
|
|
28811
28944
|
shadowSize: [41, 41]
|
|
28812
28945
|
});
|
|
28813
28946
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
28814
|
-
const { useEffect:
|
|
28947
|
+
const { useEffect: useEffect75, useRef: useRef69, useCallback: useCallback112, useState: useState107 } = React82__namespace.default;
|
|
28815
28948
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
28816
28949
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
28817
28950
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
28818
28951
|
const map = useMap();
|
|
28819
|
-
const prevRef =
|
|
28820
|
-
|
|
28952
|
+
const prevRef = useRef69({ centerLat, centerLng, zoom });
|
|
28953
|
+
useEffect75(() => {
|
|
28821
28954
|
const prev = prevRef.current;
|
|
28822
28955
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
28823
28956
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -28828,7 +28961,7 @@ var init_MapView = __esm({
|
|
|
28828
28961
|
}
|
|
28829
28962
|
function MapClickHandler({ onMapClick }) {
|
|
28830
28963
|
const map = useMap();
|
|
28831
|
-
|
|
28964
|
+
useEffect75(() => {
|
|
28832
28965
|
if (!onMapClick) return;
|
|
28833
28966
|
const handler = (e) => {
|
|
28834
28967
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -28857,7 +28990,7 @@ var init_MapView = __esm({
|
|
|
28857
28990
|
}) {
|
|
28858
28991
|
const eventBus = useEventBus3();
|
|
28859
28992
|
const [clickedPosition, setClickedPosition] = useState107(null);
|
|
28860
|
-
const handleMapClick =
|
|
28993
|
+
const handleMapClick = useCallback112((lat, lng) => {
|
|
28861
28994
|
if (showClickedPin) {
|
|
28862
28995
|
setClickedPosition({ lat, lng });
|
|
28863
28996
|
}
|
|
@@ -28866,7 +28999,7 @@ var init_MapView = __esm({
|
|
|
28866
28999
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
28867
29000
|
}
|
|
28868
29001
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
28869
|
-
const handleMarkerClick =
|
|
29002
|
+
const handleMarkerClick = useCallback112((marker) => {
|
|
28870
29003
|
onMarkerClick?.(marker);
|
|
28871
29004
|
if (markerClickEvent) {
|
|
28872
29005
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -44738,11 +44871,13 @@ function SimulationCanvas({
|
|
|
44738
44871
|
height = 400,
|
|
44739
44872
|
running,
|
|
44740
44873
|
speed = 1,
|
|
44874
|
+
bodies: externalBodies,
|
|
44741
44875
|
className
|
|
44742
44876
|
}) {
|
|
44743
44877
|
const preset = React82.useMemo(() => resolvePreset(presetProp), [presetProp]);
|
|
44744
44878
|
const canvasRef = React82.useRef(null);
|
|
44745
44879
|
const bodiesRef = React82.useRef(structuredClone(preset.bodies));
|
|
44880
|
+
const interp = useRenderInterpolation();
|
|
44746
44881
|
React82.useEffect(() => {
|
|
44747
44882
|
bodiesRef.current = structuredClone(preset.bodies);
|
|
44748
44883
|
}, [preset]);
|
|
@@ -44840,6 +44975,67 @@ function SimulationCanvas({
|
|
|
44840
44975
|
}
|
|
44841
44976
|
}, [width, height, preset]);
|
|
44842
44977
|
React82.useEffect(() => {
|
|
44978
|
+
if (!externalBodies) return;
|
|
44979
|
+
interp.onSnapshot(externalBodies.map((b) => ({ id: b.id, x: b.x, y: b.y })));
|
|
44980
|
+
}, [externalBodies]);
|
|
44981
|
+
const presetRef = React82.useRef(preset);
|
|
44982
|
+
presetRef.current = preset;
|
|
44983
|
+
const widthRef = React82.useRef(width);
|
|
44984
|
+
widthRef.current = width;
|
|
44985
|
+
const heightRef = React82.useRef(height);
|
|
44986
|
+
heightRef.current = height;
|
|
44987
|
+
React82.useEffect(() => {
|
|
44988
|
+
if (!externalBodies) return;
|
|
44989
|
+
const drawInterpolated = (positions) => {
|
|
44990
|
+
const canvas = canvasRef.current;
|
|
44991
|
+
if (!canvas) return;
|
|
44992
|
+
const ctx = canvas.getContext("2d");
|
|
44993
|
+
if (!ctx) return;
|
|
44994
|
+
const bodies = bodiesRef.current;
|
|
44995
|
+
const p2 = presetRef.current;
|
|
44996
|
+
const w = widthRef.current;
|
|
44997
|
+
const h = heightRef.current;
|
|
44998
|
+
ctx.clearRect(0, 0, w, h);
|
|
44999
|
+
ctx.fillStyle = p2.backgroundColor ?? "#1a1a2e";
|
|
45000
|
+
ctx.fillRect(0, 0, w, h);
|
|
45001
|
+
if (p2.constraints) {
|
|
45002
|
+
for (const c of p2.constraints) {
|
|
45003
|
+
const a = bodies[c.bodyA];
|
|
45004
|
+
const b = bodies[c.bodyB];
|
|
45005
|
+
if (a && b) {
|
|
45006
|
+
const aPos = positions.get(a.id) ?? a;
|
|
45007
|
+
const bPos = positions.get(b.id) ?? b;
|
|
45008
|
+
ctx.beginPath();
|
|
45009
|
+
ctx.moveTo(aPos.x, aPos.y);
|
|
45010
|
+
ctx.lineTo(bPos.x, bPos.y);
|
|
45011
|
+
ctx.strokeStyle = "#533483";
|
|
45012
|
+
ctx.lineWidth = 1;
|
|
45013
|
+
ctx.setLineDash([4, 4]);
|
|
45014
|
+
ctx.stroke();
|
|
45015
|
+
ctx.setLineDash([]);
|
|
45016
|
+
}
|
|
45017
|
+
}
|
|
45018
|
+
}
|
|
45019
|
+
for (const body of bodies) {
|
|
45020
|
+
const pos = positions.get(body.id) ?? body;
|
|
45021
|
+
ctx.beginPath();
|
|
45022
|
+
ctx.arc(pos.x, pos.y, body.radius, 0, Math.PI * 2);
|
|
45023
|
+
ctx.fillStyle = body.color ?? "#e94560";
|
|
45024
|
+
ctx.fill();
|
|
45025
|
+
if (p2.showVelocity) {
|
|
45026
|
+
ctx.beginPath();
|
|
45027
|
+
ctx.moveTo(pos.x, pos.y);
|
|
45028
|
+
ctx.lineTo(pos.x + body.vx * 0.1, pos.y + body.vy * 0.1);
|
|
45029
|
+
ctx.strokeStyle = "#16213e";
|
|
45030
|
+
ctx.lineWidth = 2;
|
|
45031
|
+
ctx.stroke();
|
|
45032
|
+
}
|
|
45033
|
+
}
|
|
45034
|
+
};
|
|
45035
|
+
return interp.startLoop(drawInterpolated);
|
|
45036
|
+
}, [externalBodies !== void 0, interp.startLoop]);
|
|
45037
|
+
React82.useEffect(() => {
|
|
45038
|
+
if (externalBodies !== void 0) return;
|
|
44843
45039
|
if (!running) return;
|
|
44844
45040
|
let raf;
|
|
44845
45041
|
const loop = () => {
|
|
@@ -44849,10 +45045,11 @@ function SimulationCanvas({
|
|
|
44849
45045
|
};
|
|
44850
45046
|
raf = requestAnimationFrame(loop);
|
|
44851
45047
|
return () => cancelAnimationFrame(raf);
|
|
44852
|
-
}, [running, step, draw]);
|
|
45048
|
+
}, [running, step, draw, externalBodies]);
|
|
44853
45049
|
React82.useEffect(() => {
|
|
45050
|
+
if (externalBodies !== void 0) return;
|
|
44854
45051
|
draw();
|
|
44855
|
-
}, [draw]);
|
|
45052
|
+
}, [draw, externalBodies]);
|
|
44856
45053
|
React82.useEffect(() => {
|
|
44857
45054
|
if (typeof window === "undefined") return;
|
|
44858
45055
|
const canvas = canvasRef.current;
|
|
@@ -44878,6 +45075,7 @@ var init_SimulationCanvas = __esm({
|
|
|
44878
45075
|
init_atoms2();
|
|
44879
45076
|
init_verificationRegistry();
|
|
44880
45077
|
init_presets();
|
|
45078
|
+
init_useRenderInterpolation();
|
|
44881
45079
|
SimulationCanvas.displayName = "SimulationCanvas";
|
|
44882
45080
|
}
|
|
44883
45081
|
});
|