@almadar/ui 5.63.2 → 5.65.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 +89 -24
- package/dist/avl/index.js +89 -24
- package/dist/components/game/molecules/IsometricCanvas.d.ts +4 -1
- package/dist/components/game/molecules/index.d.ts +1 -0
- package/dist/components/game/molecules/three/index.cjs +5 -2
- package/dist/components/game/molecules/three/index.js +5 -2
- package/dist/components/game/organisms/HexStrategyBoard.d.ts +37 -0
- package/dist/components/game/organisms/index.d.ts +2 -0
- package/dist/components/game/organisms/utils/isometric.d.ts +20 -7
- package/dist/components/index.cjs +91 -24
- package/dist/components/index.js +91 -25
- package/dist/components/marketing/organisms/HeroOrganism.d.ts +2 -2
- package/dist/components/marketing/organisms/ShowcaseOrganism.d.ts +2 -2
- package/dist/components/marketing/organisms/TeamOrganism.d.ts +2 -2
- package/dist/providers/index.cjs +89 -24
- package/dist/providers/index.js +89 -24
- package/dist/runtime/index.cjs +89 -24
- package/dist/runtime/index.js +89 -24
- package/package.json +1 -1
package/dist/providers/index.cjs
CHANGED
|
@@ -45,6 +45,7 @@ var THREE3 = require('three');
|
|
|
45
45
|
var GLTFLoader_js = require('three/examples/jsm/loaders/GLTFLoader.js');
|
|
46
46
|
var OBJLoader_js = require('three/examples/jsm/loaders/OBJLoader.js');
|
|
47
47
|
var GLTFLoader = require('three/examples/jsm/loaders/GLTFLoader');
|
|
48
|
+
var SkeletonUtils = require('three/examples/jsm/utils/SkeletonUtils');
|
|
48
49
|
var fiber = require('@react-three/fiber');
|
|
49
50
|
var drei = require('@react-three/drei');
|
|
50
51
|
var patterns = require('@almadar/patterns');
|
|
@@ -11285,16 +11286,26 @@ var init_useUnitSpriteAtlas = __esm({
|
|
|
11285
11286
|
});
|
|
11286
11287
|
|
|
11287
11288
|
// components/game/organisms/utils/isometric.ts
|
|
11288
|
-
function isoToScreen(tileX, tileY, scale, baseOffsetX) {
|
|
11289
|
+
function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
|
|
11289
11290
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
11290
11291
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
11292
|
+
if (layout === "hex") {
|
|
11293
|
+
const screenX2 = tileX * scaledTileWidth + (tileY & 1) * (scaledTileWidth / 2) + baseOffsetX;
|
|
11294
|
+
const screenY2 = tileY * (scaledFloorHeight * 0.75);
|
|
11295
|
+
return { x: screenX2, y: screenY2 };
|
|
11296
|
+
}
|
|
11291
11297
|
const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
|
|
11292
11298
|
const screenY = (tileX + tileY) * (scaledFloorHeight / 2);
|
|
11293
11299
|
return { x: screenX, y: screenY };
|
|
11294
11300
|
}
|
|
11295
|
-
function screenToIso(screenX, screenY, scale, baseOffsetX) {
|
|
11301
|
+
function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric") {
|
|
11296
11302
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
11297
11303
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
11304
|
+
if (layout === "hex") {
|
|
11305
|
+
const row = Math.round(screenY / (scaledFloorHeight * 0.75));
|
|
11306
|
+
const col = Math.round((screenX - (row & 1) * (scaledTileWidth / 2) - baseOffsetX) / scaledTileWidth);
|
|
11307
|
+
return { x: col, y: row };
|
|
11308
|
+
}
|
|
11298
11309
|
const adjustedX = screenX - baseOffsetX;
|
|
11299
11310
|
const tileX = (adjustedX / (scaledTileWidth / 2) + screenY / (scaledFloorHeight / 2)) / 2;
|
|
11300
11311
|
const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
|
|
@@ -11344,6 +11355,7 @@ function IsometricCanvas({
|
|
|
11344
11355
|
tileHoverEvent,
|
|
11345
11356
|
tileLeaveEvent,
|
|
11346
11357
|
// Rendering options
|
|
11358
|
+
tileLayout = "isometric",
|
|
11347
11359
|
scale = 0.4,
|
|
11348
11360
|
debug: debug2 = false,
|
|
11349
11361
|
backgroundImage = "",
|
|
@@ -11413,13 +11425,17 @@ function IsometricCanvas({
|
|
|
11413
11425
|
);
|
|
11414
11426
|
const sortedTiles = React85.useMemo(() => {
|
|
11415
11427
|
const tiles = [...tilesProp];
|
|
11416
|
-
|
|
11417
|
-
|
|
11418
|
-
|
|
11419
|
-
|
|
11420
|
-
|
|
11428
|
+
if (tileLayout === "hex") {
|
|
11429
|
+
tiles.sort((a, b) => a.y !== b.y ? a.y - b.y : a.x - b.x);
|
|
11430
|
+
} else {
|
|
11431
|
+
tiles.sort((a, b) => {
|
|
11432
|
+
const depthA = a.x + a.y;
|
|
11433
|
+
const depthB = b.x + b.y;
|
|
11434
|
+
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11435
|
+
});
|
|
11436
|
+
}
|
|
11421
11437
|
return tiles;
|
|
11422
|
-
}, [tilesProp]);
|
|
11438
|
+
}, [tilesProp, tileLayout]);
|
|
11423
11439
|
const gridWidth = React85.useMemo(() => {
|
|
11424
11440
|
if (sortedTiles.length === 0) return 0;
|
|
11425
11441
|
return Math.max(...sortedTiles.map((t2) => t2.x)) + 1;
|
|
@@ -11533,7 +11549,7 @@ function IsometricCanvas({
|
|
|
11533
11549
|
miniCanvas.width = mW;
|
|
11534
11550
|
miniCanvas.height = mH;
|
|
11535
11551
|
mCtx.clearRect(0, 0, mW, mH);
|
|
11536
|
-
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX));
|
|
11552
|
+
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX, tileLayout));
|
|
11537
11553
|
const minX = Math.min(...allScreenPos.map((p2) => p2.x));
|
|
11538
11554
|
const maxX = Math.max(...allScreenPos.map((p2) => p2.x + scaledTileWidth));
|
|
11539
11555
|
const minY = Math.min(...allScreenPos.map((p2) => p2.y));
|
|
@@ -11544,7 +11560,7 @@ function IsometricCanvas({
|
|
|
11544
11560
|
const offsetMx = (mW - worldW * scaleM) / 2;
|
|
11545
11561
|
const offsetMy = (mH - worldH * scaleM) / 2;
|
|
11546
11562
|
for (const tile of sortedTiles) {
|
|
11547
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11563
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11548
11564
|
const mx = (pos.x - minX) * scaleM + offsetMx;
|
|
11549
11565
|
const my = (pos.y - minY) * scaleM + offsetMy;
|
|
11550
11566
|
const mTileW = scaledTileWidth * scaleM;
|
|
@@ -11560,7 +11576,7 @@ function IsometricCanvas({
|
|
|
11560
11576
|
}
|
|
11561
11577
|
for (const unit of units) {
|
|
11562
11578
|
if (!unit.position) continue;
|
|
11563
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11579
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11564
11580
|
const mx = (pos.x + scaledTileWidth / 2 - minX) * scaleM + offsetMx;
|
|
11565
11581
|
const my = (pos.y + scaledTileHeight / 2 - minY) * scaleM + offsetMy;
|
|
11566
11582
|
mCtx.fillStyle = unit.team === "player" ? "#60a5fa" : unit.team === "enemy" ? "#f87171" : "#9ca3af";
|
|
@@ -11576,7 +11592,7 @@ function IsometricCanvas({
|
|
|
11576
11592
|
mCtx.strokeStyle = "rgba(255, 255, 255, 0.8)";
|
|
11577
11593
|
mCtx.lineWidth = 1;
|
|
11578
11594
|
mCtx.strokeRect(vLeft, vTop, vW, vH);
|
|
11579
|
-
}, [showMinimap, sortedTiles, units, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11595
|
+
}, [showMinimap, sortedTiles, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11580
11596
|
const draw = React85.useCallback((animTime) => {
|
|
11581
11597
|
const canvas = canvasRef.current;
|
|
11582
11598
|
if (!canvas) return;
|
|
@@ -11616,7 +11632,7 @@ function IsometricCanvas({
|
|
|
11616
11632
|
const visTop = cam.y - viewportSize.height / cam.zoom;
|
|
11617
11633
|
const visBottom = cam.y + viewportSize.height * 2 / cam.zoom;
|
|
11618
11634
|
for (const tile of sortedTiles) {
|
|
11619
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11635
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11620
11636
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11621
11637
|
continue;
|
|
11622
11638
|
}
|
|
@@ -11696,12 +11712,13 @@ function IsometricCanvas({
|
|
|
11696
11712
|
}
|
|
11697
11713
|
}
|
|
11698
11714
|
const sortedFeatures = [...features].sort((a, b) => {
|
|
11715
|
+
if (tileLayout === "hex") return a.y !== b.y ? a.y - b.y : a.x - b.x;
|
|
11699
11716
|
const depthA = a.x + a.y;
|
|
11700
11717
|
const depthB = b.x + b.y;
|
|
11701
11718
|
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11702
11719
|
});
|
|
11703
11720
|
for (const feature of sortedFeatures) {
|
|
11704
|
-
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX);
|
|
11721
|
+
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX, tileLayout);
|
|
11705
11722
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11706
11723
|
continue;
|
|
11707
11724
|
}
|
|
@@ -11736,12 +11753,13 @@ function IsometricCanvas({
|
|
|
11736
11753
|
}
|
|
11737
11754
|
const unitsWithPosition = units.filter((u) => !!u.position);
|
|
11738
11755
|
const sortedUnits = [...unitsWithPosition].sort((a, b) => {
|
|
11756
|
+
if (tileLayout === "hex") return a.position.y !== b.position.y ? a.position.y - b.position.y : a.position.x - b.position.x;
|
|
11739
11757
|
const depthA = a.position.x + a.position.y;
|
|
11740
11758
|
const depthB = b.position.x + b.position.y;
|
|
11741
11759
|
return depthA !== depthB ? depthA - depthB : a.position.y - b.position.y;
|
|
11742
11760
|
});
|
|
11743
11761
|
for (const unit of sortedUnits) {
|
|
11744
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11762
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11745
11763
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11746
11764
|
continue;
|
|
11747
11765
|
}
|
|
@@ -11761,7 +11779,7 @@ function IsometricCanvas({
|
|
|
11761
11779
|
drawH = maxUnitW / ar;
|
|
11762
11780
|
}
|
|
11763
11781
|
if (unit.previousPosition && (unit.previousPosition.x !== unit.position.x || unit.previousPosition.y !== unit.position.y)) {
|
|
11764
|
-
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX);
|
|
11782
|
+
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX, tileLayout);
|
|
11765
11783
|
const ghostCenterX = ghostPos.x + scaledTileWidth / 2;
|
|
11766
11784
|
const ghostGroundY = ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
|
|
11767
11785
|
ctx.save();
|
|
@@ -11890,6 +11908,7 @@ function IsometricCanvas({
|
|
|
11890
11908
|
units,
|
|
11891
11909
|
features,
|
|
11892
11910
|
selectedUnitId,
|
|
11911
|
+
tileLayout,
|
|
11893
11912
|
scale,
|
|
11894
11913
|
debug2,
|
|
11895
11914
|
resolveTerrainSpriteUrl,
|
|
@@ -11918,14 +11937,14 @@ function IsometricCanvas({
|
|
|
11918
11937
|
if (!selectedUnitId) return;
|
|
11919
11938
|
const unit = units.find((u) => u.id === selectedUnitId);
|
|
11920
11939
|
if (!unit?.position) return;
|
|
11921
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11940
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11922
11941
|
const centerX = pos.x + scaledTileWidth / 2;
|
|
11923
11942
|
const centerY = pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
|
|
11924
11943
|
targetCameraRef.current = {
|
|
11925
11944
|
x: centerX - viewportSize.width / 2,
|
|
11926
11945
|
y: centerY - viewportSize.height / 2
|
|
11927
11946
|
};
|
|
11928
|
-
}, [selectedUnitId, units, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11947
|
+
}, [selectedUnitId, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11929
11948
|
React85.useEffect(() => {
|
|
11930
11949
|
const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
|
|
11931
11950
|
draw(animTimeRef.current);
|
|
@@ -11958,13 +11977,13 @@ function IsometricCanvas({
|
|
|
11958
11977
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11959
11978
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11960
11979
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11961
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11980
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11962
11981
|
const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
|
|
11963
11982
|
if (tileExists) {
|
|
11964
11983
|
if (tileHoverEvent) eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
|
|
11965
11984
|
onTileHover?.(isoPos.x, isoPos.y);
|
|
11966
11985
|
}
|
|
11967
|
-
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11986
|
+
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11968
11987
|
const handleCanvasPointerUp = React85.useCallback((e) => {
|
|
11969
11988
|
singlePointerActiveRef.current = false;
|
|
11970
11989
|
if (enableCamera) handlePointerUp();
|
|
@@ -11973,7 +11992,7 @@ function IsometricCanvas({
|
|
|
11973
11992
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11974
11993
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11975
11994
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11976
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11995
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11977
11996
|
const clickedUnit = units.find((u) => u.position?.x === isoPos.x && u.position?.y === isoPos.y);
|
|
11978
11997
|
if (clickedUnit && (onUnitClick || unitClickEvent)) {
|
|
11979
11998
|
if (unitClickEvent) eventBus.emit(`UI:${unitClickEvent}`, { unitId: clickedUnit.id });
|
|
@@ -11985,7 +12004,7 @@ function IsometricCanvas({
|
|
|
11985
12004
|
onTileClick?.(isoPos.x, isoPos.y);
|
|
11986
12005
|
}
|
|
11987
12006
|
}
|
|
11988
|
-
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
12007
|
+
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11989
12008
|
const handleCanvasPointerLeave = React85.useCallback(() => {
|
|
11990
12009
|
handleMouseLeave();
|
|
11991
12010
|
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
@@ -43261,7 +43280,8 @@ function ModelLoader({
|
|
|
43261
43280
|
const { model: loadedModel, isLoading, error } = useGLTFModel(url, resourceBasePath);
|
|
43262
43281
|
const model = React85.useMemo(() => {
|
|
43263
43282
|
if (!loadedModel) return null;
|
|
43264
|
-
const cloned =
|
|
43283
|
+
const cloned = SkeletonUtils.clone(loadedModel);
|
|
43284
|
+
cloned.updateMatrixWorld(true);
|
|
43265
43285
|
cloned.traverse((child) => {
|
|
43266
43286
|
if (child instanceof THREE3__namespace.Mesh) {
|
|
43267
43287
|
child.castShadow = castShadow;
|
|
@@ -43276,7 +43296,8 @@ function ModelLoader({
|
|
|
43276
43296
|
const size = new THREE3__namespace.Vector3();
|
|
43277
43297
|
box.getSize(size);
|
|
43278
43298
|
const maxDim = Math.max(size.x, size.y, size.z);
|
|
43279
|
-
|
|
43299
|
+
if (!Number.isFinite(maxDim) || maxDim < 0.05) return 1;
|
|
43300
|
+
return 1 / maxDim;
|
|
43280
43301
|
}, [model]);
|
|
43281
43302
|
const scaleArray = React85.useMemo(() => {
|
|
43282
43303
|
const base = typeof scale === "number" ? [scale, scale, scale] : scale;
|
|
@@ -44558,6 +44579,48 @@ var init_HeroOrganism = __esm({
|
|
|
44558
44579
|
_HeroClickInterceptor.displayName = "_HeroClickInterceptor";
|
|
44559
44580
|
}
|
|
44560
44581
|
});
|
|
44582
|
+
function HexStrategyBoard({
|
|
44583
|
+
tiles,
|
|
44584
|
+
units,
|
|
44585
|
+
features,
|
|
44586
|
+
assetManifest,
|
|
44587
|
+
assetBaseUrl,
|
|
44588
|
+
scale = 0.45,
|
|
44589
|
+
showMinimap = true,
|
|
44590
|
+
enableCamera = true,
|
|
44591
|
+
tileClickEvent,
|
|
44592
|
+
unitClickEvent,
|
|
44593
|
+
isLoading,
|
|
44594
|
+
error,
|
|
44595
|
+
className
|
|
44596
|
+
}) {
|
|
44597
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("hex-strategy-board relative w-full h-full", className), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
44598
|
+
IsometricCanvas_default,
|
|
44599
|
+
{
|
|
44600
|
+
tileLayout: "hex",
|
|
44601
|
+
tiles,
|
|
44602
|
+
units,
|
|
44603
|
+
features,
|
|
44604
|
+
assetManifest,
|
|
44605
|
+
assetBaseUrl,
|
|
44606
|
+
scale,
|
|
44607
|
+
showMinimap,
|
|
44608
|
+
enableCamera,
|
|
44609
|
+
tileClickEvent,
|
|
44610
|
+
unitClickEvent,
|
|
44611
|
+
isLoading,
|
|
44612
|
+
error
|
|
44613
|
+
}
|
|
44614
|
+
) });
|
|
44615
|
+
}
|
|
44616
|
+
var init_HexStrategyBoard = __esm({
|
|
44617
|
+
"components/game/organisms/HexStrategyBoard.tsx"() {
|
|
44618
|
+
"use client";
|
|
44619
|
+
init_cn();
|
|
44620
|
+
init_IsometricCanvas();
|
|
44621
|
+
HexStrategyBoard.displayName = "HexStrategyBoard";
|
|
44622
|
+
}
|
|
44623
|
+
});
|
|
44561
44624
|
var LandingPageTemplate;
|
|
44562
44625
|
var init_LandingPageTemplate = __esm({
|
|
44563
44626
|
"components/marketing/templates/LandingPageTemplate.tsx"() {
|
|
@@ -52367,6 +52430,7 @@ var init_component_registry_generated = __esm({
|
|
|
52367
52430
|
init_HealthPanel();
|
|
52368
52431
|
init_HeroOrganism();
|
|
52369
52432
|
init_HeroSection();
|
|
52433
|
+
init_HexStrategyBoard();
|
|
52370
52434
|
init_Icon();
|
|
52371
52435
|
init_InfiniteScrollSentinel();
|
|
52372
52436
|
init_Input();
|
|
@@ -52703,6 +52767,7 @@ var init_component_registry_generated = __esm({
|
|
|
52703
52767
|
"HealthPanel": HealthPanel,
|
|
52704
52768
|
"HeroOrganism": HeroOrganism,
|
|
52705
52769
|
"HeroSection": HeroSection,
|
|
52770
|
+
"HexStrategyBoard": HexStrategyBoard,
|
|
52706
52771
|
"Icon": Icon,
|
|
52707
52772
|
"InfiniteScrollSentinel": InfiniteScrollSentinel,
|
|
52708
52773
|
"Input": Input,
|
package/dist/providers/index.js
CHANGED
|
@@ -45,6 +45,7 @@ import * as THREE3 from 'three';
|
|
|
45
45
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
46
46
|
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
|
|
47
47
|
import { GLTFLoader as GLTFLoader$1 } from 'three/examples/jsm/loaders/GLTFLoader';
|
|
48
|
+
import { clone } from 'three/examples/jsm/utils/SkeletonUtils';
|
|
48
49
|
import { Canvas, useLoader, useFrame, useThree } from '@react-three/fiber';
|
|
49
50
|
import { Billboard, Grid as Grid$1, OrbitControls } from '@react-three/drei';
|
|
50
51
|
import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1 } from '@almadar/patterns';
|
|
@@ -11238,16 +11239,26 @@ var init_useUnitSpriteAtlas = __esm({
|
|
|
11238
11239
|
});
|
|
11239
11240
|
|
|
11240
11241
|
// components/game/organisms/utils/isometric.ts
|
|
11241
|
-
function isoToScreen(tileX, tileY, scale, baseOffsetX) {
|
|
11242
|
+
function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
|
|
11242
11243
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
11243
11244
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
11245
|
+
if (layout === "hex") {
|
|
11246
|
+
const screenX2 = tileX * scaledTileWidth + (tileY & 1) * (scaledTileWidth / 2) + baseOffsetX;
|
|
11247
|
+
const screenY2 = tileY * (scaledFloorHeight * 0.75);
|
|
11248
|
+
return { x: screenX2, y: screenY2 };
|
|
11249
|
+
}
|
|
11244
11250
|
const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
|
|
11245
11251
|
const screenY = (tileX + tileY) * (scaledFloorHeight / 2);
|
|
11246
11252
|
return { x: screenX, y: screenY };
|
|
11247
11253
|
}
|
|
11248
|
-
function screenToIso(screenX, screenY, scale, baseOffsetX) {
|
|
11254
|
+
function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric") {
|
|
11249
11255
|
const scaledTileWidth = TILE_WIDTH * scale;
|
|
11250
11256
|
const scaledFloorHeight = FLOOR_HEIGHT * scale;
|
|
11257
|
+
if (layout === "hex") {
|
|
11258
|
+
const row = Math.round(screenY / (scaledFloorHeight * 0.75));
|
|
11259
|
+
const col = Math.round((screenX - (row & 1) * (scaledTileWidth / 2) - baseOffsetX) / scaledTileWidth);
|
|
11260
|
+
return { x: col, y: row };
|
|
11261
|
+
}
|
|
11251
11262
|
const adjustedX = screenX - baseOffsetX;
|
|
11252
11263
|
const tileX = (adjustedX / (scaledTileWidth / 2) + screenY / (scaledFloorHeight / 2)) / 2;
|
|
11253
11264
|
const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
|
|
@@ -11297,6 +11308,7 @@ function IsometricCanvas({
|
|
|
11297
11308
|
tileHoverEvent,
|
|
11298
11309
|
tileLeaveEvent,
|
|
11299
11310
|
// Rendering options
|
|
11311
|
+
tileLayout = "isometric",
|
|
11300
11312
|
scale = 0.4,
|
|
11301
11313
|
debug: debug2 = false,
|
|
11302
11314
|
backgroundImage = "",
|
|
@@ -11366,13 +11378,17 @@ function IsometricCanvas({
|
|
|
11366
11378
|
);
|
|
11367
11379
|
const sortedTiles = useMemo(() => {
|
|
11368
11380
|
const tiles = [...tilesProp];
|
|
11369
|
-
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
11381
|
+
if (tileLayout === "hex") {
|
|
11382
|
+
tiles.sort((a, b) => a.y !== b.y ? a.y - b.y : a.x - b.x);
|
|
11383
|
+
} else {
|
|
11384
|
+
tiles.sort((a, b) => {
|
|
11385
|
+
const depthA = a.x + a.y;
|
|
11386
|
+
const depthB = b.x + b.y;
|
|
11387
|
+
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11388
|
+
});
|
|
11389
|
+
}
|
|
11374
11390
|
return tiles;
|
|
11375
|
-
}, [tilesProp]);
|
|
11391
|
+
}, [tilesProp, tileLayout]);
|
|
11376
11392
|
const gridWidth = useMemo(() => {
|
|
11377
11393
|
if (sortedTiles.length === 0) return 0;
|
|
11378
11394
|
return Math.max(...sortedTiles.map((t2) => t2.x)) + 1;
|
|
@@ -11486,7 +11502,7 @@ function IsometricCanvas({
|
|
|
11486
11502
|
miniCanvas.width = mW;
|
|
11487
11503
|
miniCanvas.height = mH;
|
|
11488
11504
|
mCtx.clearRect(0, 0, mW, mH);
|
|
11489
|
-
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX));
|
|
11505
|
+
const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX, tileLayout));
|
|
11490
11506
|
const minX = Math.min(...allScreenPos.map((p2) => p2.x));
|
|
11491
11507
|
const maxX = Math.max(...allScreenPos.map((p2) => p2.x + scaledTileWidth));
|
|
11492
11508
|
const minY = Math.min(...allScreenPos.map((p2) => p2.y));
|
|
@@ -11497,7 +11513,7 @@ function IsometricCanvas({
|
|
|
11497
11513
|
const offsetMx = (mW - worldW * scaleM) / 2;
|
|
11498
11514
|
const offsetMy = (mH - worldH * scaleM) / 2;
|
|
11499
11515
|
for (const tile of sortedTiles) {
|
|
11500
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11516
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11501
11517
|
const mx = (pos.x - minX) * scaleM + offsetMx;
|
|
11502
11518
|
const my = (pos.y - minY) * scaleM + offsetMy;
|
|
11503
11519
|
const mTileW = scaledTileWidth * scaleM;
|
|
@@ -11513,7 +11529,7 @@ function IsometricCanvas({
|
|
|
11513
11529
|
}
|
|
11514
11530
|
for (const unit of units) {
|
|
11515
11531
|
if (!unit.position) continue;
|
|
11516
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11532
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11517
11533
|
const mx = (pos.x + scaledTileWidth / 2 - minX) * scaleM + offsetMx;
|
|
11518
11534
|
const my = (pos.y + scaledTileHeight / 2 - minY) * scaleM + offsetMy;
|
|
11519
11535
|
mCtx.fillStyle = unit.team === "player" ? "#60a5fa" : unit.team === "enemy" ? "#f87171" : "#9ca3af";
|
|
@@ -11529,7 +11545,7 @@ function IsometricCanvas({
|
|
|
11529
11545
|
mCtx.strokeStyle = "rgba(255, 255, 255, 0.8)";
|
|
11530
11546
|
mCtx.lineWidth = 1;
|
|
11531
11547
|
mCtx.strokeRect(vLeft, vTop, vW, vH);
|
|
11532
|
-
}, [showMinimap, sortedTiles, units, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11548
|
+
}, [showMinimap, sortedTiles, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
|
|
11533
11549
|
const draw = useCallback((animTime) => {
|
|
11534
11550
|
const canvas = canvasRef.current;
|
|
11535
11551
|
if (!canvas) return;
|
|
@@ -11569,7 +11585,7 @@ function IsometricCanvas({
|
|
|
11569
11585
|
const visTop = cam.y - viewportSize.height / cam.zoom;
|
|
11570
11586
|
const visBottom = cam.y + viewportSize.height * 2 / cam.zoom;
|
|
11571
11587
|
for (const tile of sortedTiles) {
|
|
11572
|
-
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX);
|
|
11588
|
+
const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
|
|
11573
11589
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11574
11590
|
continue;
|
|
11575
11591
|
}
|
|
@@ -11649,12 +11665,13 @@ function IsometricCanvas({
|
|
|
11649
11665
|
}
|
|
11650
11666
|
}
|
|
11651
11667
|
const sortedFeatures = [...features].sort((a, b) => {
|
|
11668
|
+
if (tileLayout === "hex") return a.y !== b.y ? a.y - b.y : a.x - b.x;
|
|
11652
11669
|
const depthA = a.x + a.y;
|
|
11653
11670
|
const depthB = b.x + b.y;
|
|
11654
11671
|
return depthA !== depthB ? depthA - depthB : a.y - b.y;
|
|
11655
11672
|
});
|
|
11656
11673
|
for (const feature of sortedFeatures) {
|
|
11657
|
-
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX);
|
|
11674
|
+
const pos = isoToScreen(feature.x, feature.y, scale, baseOffsetX, tileLayout);
|
|
11658
11675
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11659
11676
|
continue;
|
|
11660
11677
|
}
|
|
@@ -11689,12 +11706,13 @@ function IsometricCanvas({
|
|
|
11689
11706
|
}
|
|
11690
11707
|
const unitsWithPosition = units.filter((u) => !!u.position);
|
|
11691
11708
|
const sortedUnits = [...unitsWithPosition].sort((a, b) => {
|
|
11709
|
+
if (tileLayout === "hex") return a.position.y !== b.position.y ? a.position.y - b.position.y : a.position.x - b.position.x;
|
|
11692
11710
|
const depthA = a.position.x + a.position.y;
|
|
11693
11711
|
const depthB = b.position.x + b.position.y;
|
|
11694
11712
|
return depthA !== depthB ? depthA - depthB : a.position.y - b.position.y;
|
|
11695
11713
|
});
|
|
11696
11714
|
for (const unit of sortedUnits) {
|
|
11697
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11715
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11698
11716
|
if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
|
|
11699
11717
|
continue;
|
|
11700
11718
|
}
|
|
@@ -11714,7 +11732,7 @@ function IsometricCanvas({
|
|
|
11714
11732
|
drawH = maxUnitW / ar;
|
|
11715
11733
|
}
|
|
11716
11734
|
if (unit.previousPosition && (unit.previousPosition.x !== unit.position.x || unit.previousPosition.y !== unit.position.y)) {
|
|
11717
|
-
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX);
|
|
11735
|
+
const ghostPos = isoToScreen(unit.previousPosition.x, unit.previousPosition.y, scale, baseOffsetX, tileLayout);
|
|
11718
11736
|
const ghostCenterX = ghostPos.x + scaledTileWidth / 2;
|
|
11719
11737
|
const ghostGroundY = ghostPos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
|
|
11720
11738
|
ctx.save();
|
|
@@ -11843,6 +11861,7 @@ function IsometricCanvas({
|
|
|
11843
11861
|
units,
|
|
11844
11862
|
features,
|
|
11845
11863
|
selectedUnitId,
|
|
11864
|
+
tileLayout,
|
|
11846
11865
|
scale,
|
|
11847
11866
|
debug2,
|
|
11848
11867
|
resolveTerrainSpriteUrl,
|
|
@@ -11871,14 +11890,14 @@ function IsometricCanvas({
|
|
|
11871
11890
|
if (!selectedUnitId) return;
|
|
11872
11891
|
const unit = units.find((u) => u.id === selectedUnitId);
|
|
11873
11892
|
if (!unit?.position) return;
|
|
11874
|
-
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX);
|
|
11893
|
+
const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
|
|
11875
11894
|
const centerX = pos.x + scaledTileWidth / 2;
|
|
11876
11895
|
const centerY = pos.y + scaledDiamondTopY + scaledFloorHeight / 2;
|
|
11877
11896
|
targetCameraRef.current = {
|
|
11878
11897
|
x: centerX - viewportSize.width / 2,
|
|
11879
11898
|
y: centerY - viewportSize.height / 2
|
|
11880
11899
|
};
|
|
11881
|
-
}, [selectedUnitId, units, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11900
|
+
}, [selectedUnitId, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
|
|
11882
11901
|
useEffect(() => {
|
|
11883
11902
|
const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
|
|
11884
11903
|
draw(animTimeRef.current);
|
|
@@ -11911,13 +11930,13 @@ function IsometricCanvas({
|
|
|
11911
11930
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11912
11931
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11913
11932
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11914
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11933
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11915
11934
|
const tileExists = tilesProp.some((t2) => t2.x === isoPos.x && t2.y === isoPos.y);
|
|
11916
11935
|
if (tileExists) {
|
|
11917
11936
|
if (tileHoverEvent) eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
|
|
11918
11937
|
onTileHover?.(isoPos.x, isoPos.y);
|
|
11919
11938
|
}
|
|
11920
|
-
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11939
|
+
}, [onTileHover, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, tilesProp, tileHoverEvent, eventBus]);
|
|
11921
11940
|
const handleCanvasPointerUp = useCallback((e) => {
|
|
11922
11941
|
singlePointerActiveRef.current = false;
|
|
11923
11942
|
if (enableCamera) handlePointerUp();
|
|
@@ -11926,7 +11945,7 @@ function IsometricCanvas({
|
|
|
11926
11945
|
const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
|
|
11927
11946
|
const adjustedX = world.x - scaledTileWidth / 2;
|
|
11928
11947
|
const adjustedY = world.y - scaledDiamondTopY - scaledFloorHeight / 2;
|
|
11929
|
-
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX);
|
|
11948
|
+
const isoPos = screenToIso(adjustedX, adjustedY, scale, baseOffsetX, tileLayout);
|
|
11930
11949
|
const clickedUnit = units.find((u) => u.position?.x === isoPos.x && u.position?.y === isoPos.y);
|
|
11931
11950
|
if (clickedUnit && (onUnitClick || unitClickEvent)) {
|
|
11932
11951
|
if (unitClickEvent) eventBus.emit(`UI:${unitClickEvent}`, { unitId: clickedUnit.id });
|
|
@@ -11938,7 +11957,7 @@ function IsometricCanvas({
|
|
|
11938
11957
|
onTileClick?.(isoPos.x, isoPos.y);
|
|
11939
11958
|
}
|
|
11940
11959
|
}
|
|
11941
|
-
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11960
|
+
}, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, tileLayout, scale, baseOffsetX, units, tilesProp, onUnitClick, onTileClick, unitClickEvent, tileClickEvent, eventBus]);
|
|
11942
11961
|
const handleCanvasPointerLeave = useCallback(() => {
|
|
11943
11962
|
handleMouseLeave();
|
|
11944
11963
|
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
@@ -43214,7 +43233,8 @@ function ModelLoader({
|
|
|
43214
43233
|
const { model: loadedModel, isLoading, error } = useGLTFModel(url, resourceBasePath);
|
|
43215
43234
|
const model = useMemo(() => {
|
|
43216
43235
|
if (!loadedModel) return null;
|
|
43217
|
-
const cloned =
|
|
43236
|
+
const cloned = clone(loadedModel);
|
|
43237
|
+
cloned.updateMatrixWorld(true);
|
|
43218
43238
|
cloned.traverse((child) => {
|
|
43219
43239
|
if (child instanceof THREE3.Mesh) {
|
|
43220
43240
|
child.castShadow = castShadow;
|
|
@@ -43229,7 +43249,8 @@ function ModelLoader({
|
|
|
43229
43249
|
const size = new THREE3.Vector3();
|
|
43230
43250
|
box.getSize(size);
|
|
43231
43251
|
const maxDim = Math.max(size.x, size.y, size.z);
|
|
43232
|
-
|
|
43252
|
+
if (!Number.isFinite(maxDim) || maxDim < 0.05) return 1;
|
|
43253
|
+
return 1 / maxDim;
|
|
43233
43254
|
}, [model]);
|
|
43234
43255
|
const scaleArray = useMemo(() => {
|
|
43235
43256
|
const base = typeof scale === "number" ? [scale, scale, scale] : scale;
|
|
@@ -44511,6 +44532,48 @@ var init_HeroOrganism = __esm({
|
|
|
44511
44532
|
_HeroClickInterceptor.displayName = "_HeroClickInterceptor";
|
|
44512
44533
|
}
|
|
44513
44534
|
});
|
|
44535
|
+
function HexStrategyBoard({
|
|
44536
|
+
tiles,
|
|
44537
|
+
units,
|
|
44538
|
+
features,
|
|
44539
|
+
assetManifest,
|
|
44540
|
+
assetBaseUrl,
|
|
44541
|
+
scale = 0.45,
|
|
44542
|
+
showMinimap = true,
|
|
44543
|
+
enableCamera = true,
|
|
44544
|
+
tileClickEvent,
|
|
44545
|
+
unitClickEvent,
|
|
44546
|
+
isLoading,
|
|
44547
|
+
error,
|
|
44548
|
+
className
|
|
44549
|
+
}) {
|
|
44550
|
+
return /* @__PURE__ */ jsx("div", { className: cn("hex-strategy-board relative w-full h-full", className), children: /* @__PURE__ */ jsx(
|
|
44551
|
+
IsometricCanvas_default,
|
|
44552
|
+
{
|
|
44553
|
+
tileLayout: "hex",
|
|
44554
|
+
tiles,
|
|
44555
|
+
units,
|
|
44556
|
+
features,
|
|
44557
|
+
assetManifest,
|
|
44558
|
+
assetBaseUrl,
|
|
44559
|
+
scale,
|
|
44560
|
+
showMinimap,
|
|
44561
|
+
enableCamera,
|
|
44562
|
+
tileClickEvent,
|
|
44563
|
+
unitClickEvent,
|
|
44564
|
+
isLoading,
|
|
44565
|
+
error
|
|
44566
|
+
}
|
|
44567
|
+
) });
|
|
44568
|
+
}
|
|
44569
|
+
var init_HexStrategyBoard = __esm({
|
|
44570
|
+
"components/game/organisms/HexStrategyBoard.tsx"() {
|
|
44571
|
+
"use client";
|
|
44572
|
+
init_cn();
|
|
44573
|
+
init_IsometricCanvas();
|
|
44574
|
+
HexStrategyBoard.displayName = "HexStrategyBoard";
|
|
44575
|
+
}
|
|
44576
|
+
});
|
|
44514
44577
|
var LandingPageTemplate;
|
|
44515
44578
|
var init_LandingPageTemplate = __esm({
|
|
44516
44579
|
"components/marketing/templates/LandingPageTemplate.tsx"() {
|
|
@@ -52320,6 +52383,7 @@ var init_component_registry_generated = __esm({
|
|
|
52320
52383
|
init_HealthPanel();
|
|
52321
52384
|
init_HeroOrganism();
|
|
52322
52385
|
init_HeroSection();
|
|
52386
|
+
init_HexStrategyBoard();
|
|
52323
52387
|
init_Icon();
|
|
52324
52388
|
init_InfiniteScrollSentinel();
|
|
52325
52389
|
init_Input();
|
|
@@ -52656,6 +52720,7 @@ var init_component_registry_generated = __esm({
|
|
|
52656
52720
|
"HealthPanel": HealthPanel,
|
|
52657
52721
|
"HeroOrganism": HeroOrganism,
|
|
52658
52722
|
"HeroSection": HeroSection,
|
|
52723
|
+
"HexStrategyBoard": HexStrategyBoard,
|
|
52659
52724
|
"Icon": Icon,
|
|
52660
52725
|
"InfiniteScrollSentinel": InfiniteScrollSentinel,
|
|
52661
52726
|
"Input": Input,
|