@principal-ai/file-city-react 0.5.24 → 0.5.26
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileCity3D.d.ts","sourceRoot":"","sources":["../../../src/components/FileCity3D/FileCity3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AAMjF,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,EAEb,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,OAAO,QAAQ,OAAO,CAAC;IAErB,UAAU,GAAG,CAAC;QAEZ,UAAU,iBAAkB,SAAQ,aAAa;SAAG;KACrD;CACF;AAGD,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AAGrD,MAAM,WAAW,cAAc;IAC7B,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;CAC5B;AAED,gDAAgD;AAChD,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,aAAa,GACb,UAAU,GACV,MAAM,CAAC;AAGX,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wCAAwC;AACxC,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,QAAQ,CAAC;AAErD,oFAAoF;AACpF,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,EAAE,WAAW,EAS9C,CAAC;
|
|
1
|
+
{"version":3,"file":"FileCity3D.d.ts","sourceRoot":"","sources":["../../../src/components/FileCity3D/FileCity3D.tsx"],"names":[],"mappings":"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"}
|
|
@@ -472,59 +472,37 @@ function InstancedBuildings({ buildings, centerOffset, onHover, onClick, hovered
|
|
|
472
472
|
buildingIndex: d.index,
|
|
473
473
|
})), growProgress: growProgress, minHeight: minHeight, baseOffset: baseOffset, springDuration: springDuration, heightMultipliersRef: heightMultipliersRef })] }));
|
|
474
474
|
}
|
|
475
|
-
function AnimatedIcon({ x, z, targetHeight, iconSize, texture, opacity, growProgress,
|
|
475
|
+
function AnimatedIcon({ x, z, targetHeight, iconSize, texture, opacity, growProgress, }) {
|
|
476
476
|
const meshRef = useRef(null);
|
|
477
|
-
const startTimeRef = useRef(null);
|
|
478
477
|
const materialRef = useRef(null);
|
|
479
|
-
useFrame((
|
|
478
|
+
useFrame(() => {
|
|
480
479
|
if (!meshRef.current)
|
|
481
480
|
return;
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
}
|
|
485
|
-
const currentTime = clock.elapsedTime * 1000;
|
|
486
|
-
const animStartTime = startTimeRef.current ?? currentTime;
|
|
487
|
-
// Calculate per-icon animation progress
|
|
488
|
-
const elapsed = currentTime - animStartTime - staggerDelayMs;
|
|
489
|
-
let animProgress = growProgress;
|
|
490
|
-
if (growProgress > 0 && elapsed >= 0) {
|
|
491
|
-
const t = Math.min(elapsed / springDuration, 1);
|
|
492
|
-
const eased = 1 - Math.pow(1 - t, 3);
|
|
493
|
-
animProgress = eased * growProgress;
|
|
494
|
-
}
|
|
495
|
-
else if (growProgress > 0 && elapsed < 0) {
|
|
496
|
-
animProgress = 0;
|
|
497
|
-
}
|
|
481
|
+
// Icons track the global growProgress directly (no stagger)
|
|
482
|
+
// This keeps them in sync with the building heights
|
|
498
483
|
const minHeight = 0.3;
|
|
499
484
|
const baseOffset = 0.2;
|
|
500
|
-
const height =
|
|
485
|
+
const height = growProgress * targetHeight + minHeight;
|
|
501
486
|
const buildingTop = height + baseOffset;
|
|
502
|
-
// When flat (
|
|
503
|
-
// When grown (
|
|
487
|
+
// When flat (growProgress=0): icon lies flat at ground level
|
|
488
|
+
// When grown (growProgress=1): icon lies flat above building roof
|
|
504
489
|
const flatY = minHeight + baseOffset + 0.5;
|
|
505
|
-
const grownY = buildingTop +
|
|
506
|
-
const yPosition = flatY + (grownY - flatY) *
|
|
490
|
+
const grownY = buildingTop + 0.5;
|
|
491
|
+
const yPosition = flatY + (grownY - flatY) * growProgress;
|
|
507
492
|
meshRef.current.position.y = yPosition;
|
|
508
|
-
//
|
|
509
|
-
|
|
510
|
-
// Grown: 0 (facing forward)
|
|
511
|
-
const flatRotationX = -Math.PI / 2;
|
|
512
|
-
const grownRotationX = 0;
|
|
513
|
-
meshRef.current.rotation.x = flatRotationX + (grownRotationX - flatRotationX) * animProgress;
|
|
493
|
+
// Keep icon flat (facing up) at all times
|
|
494
|
+
meshRef.current.rotation.x = -Math.PI / 2;
|
|
514
495
|
if (materialRef.current) {
|
|
515
|
-
|
|
516
|
-
const minOpacity = 0.8;
|
|
517
|
-
const effectiveOpacity = minOpacity + (1 - minOpacity) * animProgress;
|
|
518
|
-
materialRef.current.opacity = opacity * effectiveOpacity;
|
|
496
|
+
materialRef.current.opacity = opacity;
|
|
519
497
|
}
|
|
520
498
|
});
|
|
521
499
|
return (_jsxs("mesh", { ref: meshRef, position: [x, 0, z], scale: [iconSize, iconSize, 1], raycast: () => null, children: [_jsx("planeGeometry", { args: [1, 1] }), _jsx("meshBasicMaterial", { ref: materialRef, map: texture, transparent: true, opacity: 0.8, depthTest: true, depthWrite: false, side: THREE.DoubleSide })] }));
|
|
522
500
|
}
|
|
523
|
-
function BuildingIcons({ buildings, centerOffset, growProgress, heightScaling, linearScale, flatPatterns, highlightLayers, isolationMode, hasActiveHighlights,
|
|
501
|
+
function BuildingIcons({ buildings, centerOffset, growProgress, heightScaling, linearScale, flatPatterns, highlightLayers, isolationMode, hasActiveHighlights, }) {
|
|
524
502
|
// Pre-compute buildings with icons
|
|
525
503
|
const buildingsWithIcons = useMemo(() => {
|
|
526
504
|
return buildings
|
|
527
|
-
.map((building
|
|
505
|
+
.map((building) => {
|
|
528
506
|
const config = getConfigForFile(building);
|
|
529
507
|
if (!config.icon)
|
|
530
508
|
return null;
|
|
@@ -533,14 +511,13 @@ function BuildingIcons({ buildings, centerOffset, growProgress, heightScaling, l
|
|
|
533
511
|
const shouldDim = hasActiveHighlights && !isHighlighted;
|
|
534
512
|
const shouldHide = shouldDim && isolationMode === 'hide';
|
|
535
513
|
const shouldCollapse = shouldDim && isolationMode === 'collapse';
|
|
536
|
-
|
|
514
|
+
// Hide icons for buildings that are hidden or collapsed
|
|
515
|
+
if (shouldHide || shouldCollapse)
|
|
537
516
|
return null;
|
|
538
517
|
const fullHeight = calculateBuildingHeight(building, heightScaling, linearScale, flatPatterns);
|
|
539
|
-
const targetHeight =
|
|
518
|
+
const targetHeight = fullHeight;
|
|
540
519
|
const x = building.position.x - centerOffset.x;
|
|
541
520
|
const z = building.position.z - centerOffset.z;
|
|
542
|
-
const staggerIndex = staggerIndices[index] ?? index;
|
|
543
|
-
const staggerDelayMs = staggerDelay * staggerIndex;
|
|
544
521
|
return {
|
|
545
522
|
building,
|
|
546
523
|
config,
|
|
@@ -548,7 +525,6 @@ function BuildingIcons({ buildings, centerOffset, growProgress, heightScaling, l
|
|
|
548
525
|
z,
|
|
549
526
|
targetHeight,
|
|
550
527
|
shouldDim,
|
|
551
|
-
staggerDelayMs,
|
|
552
528
|
};
|
|
553
529
|
})
|
|
554
530
|
.filter(Boolean);
|
|
@@ -561,11 +537,9 @@ function BuildingIcons({ buildings, centerOffset, growProgress, heightScaling, l
|
|
|
561
537
|
heightScaling,
|
|
562
538
|
linearScale,
|
|
563
539
|
flatPatterns,
|
|
564
|
-
staggerIndices,
|
|
565
|
-
staggerDelay,
|
|
566
540
|
]);
|
|
567
541
|
// Icons are now always rendered (flat or grown)
|
|
568
|
-
return (_jsx(_Fragment, { children: buildingsWithIcons.map(({ building, config, x, z, targetHeight, shouldDim
|
|
542
|
+
return (_jsx(_Fragment, { children: buildingsWithIcons.map(({ building, config, x, z, targetHeight, shouldDim }) => {
|
|
569
543
|
const icon = config.icon;
|
|
570
544
|
const texture = getIconTexture(icon.name, icon.color || '#ffffff');
|
|
571
545
|
if (!texture)
|
|
@@ -575,7 +549,7 @@ function BuildingIcons({ buildings, centerOffset, growProgress, heightScaling, l
|
|
|
575
549
|
const minDimension = Math.min(width, depth);
|
|
576
550
|
const iconSize = minDimension * (icon.size || 0.6) * 1.7;
|
|
577
551
|
const opacity = shouldDim && isolationMode === 'transparent' ? 0.3 : 1;
|
|
578
|
-
return (_jsx(AnimatedIcon, { x: x, z: z, targetHeight: targetHeight, iconSize: iconSize, texture: texture, opacity: opacity, growProgress: growProgress
|
|
552
|
+
return (_jsx(AnimatedIcon, { x: x, z: z, targetHeight: targetHeight, iconSize: iconSize, texture: texture, opacity: opacity, growProgress: growProgress }, building.path));
|
|
579
553
|
}) }));
|
|
580
554
|
}
|
|
581
555
|
function DistrictFloor({ district, centerOffset, highlightColor, growProgress }) {
|
|
@@ -599,10 +573,10 @@ function DistrictFloor({ district, centerOffset, highlightColor, growProgress })
|
|
|
599
573
|
const flatY = 0.5;
|
|
600
574
|
const grownY = 1.5;
|
|
601
575
|
const textY = flatY + (grownY - flatY) * growProgress;
|
|
602
|
-
const flatZ =
|
|
603
|
-
const grownZ = depth / 2 + 2; //
|
|
576
|
+
const flatZ = depth / 2 - 6; // Near bottom of district when flat, with padding
|
|
577
|
+
const grownZ = depth / 2 + 2; // Just outside edge when grown
|
|
604
578
|
const textZ = flatZ + (grownZ - flatZ) * growProgress;
|
|
605
|
-
return (_jsxs("group", { position: [centerX, 0, centerZ], children: [_jsxs("lineSegments", { rotation: [-Math.PI / 2, 0, 0], position: [0, floorY, 0], renderOrder: -1, children: [_jsx("edgesGeometry", { args: [new THREE.PlaneGeometry(width, depth)], attach: "geometry" }), _jsx("lineBasicMaterial", { color: borderColor, linewidth: lineWidth, depthWrite: false })] }), highlightColor && (_jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], position: [0, floorY - 0.1, 0], renderOrder: -2, children: [_jsx("planeGeometry", { args: [width, depth] }), _jsx("meshBasicMaterial", { color: highlightColor, transparent: true, opacity: 0.15, depthWrite: false })] })),
|
|
579
|
+
return (_jsxs("group", { position: [centerX, 0, centerZ], children: [_jsxs("lineSegments", { rotation: [-Math.PI / 2, 0, 0], position: [0, floorY, 0], renderOrder: -1, children: [_jsx("edgesGeometry", { args: [new THREE.PlaneGeometry(width, depth)], attach: "geometry" }), _jsx("lineBasicMaterial", { color: borderColor, linewidth: lineWidth, depthWrite: false })] }), highlightColor && (_jsxs("mesh", { rotation: [-Math.PI / 2, 0, 0], position: [0, floorY - 0.1, 0], renderOrder: -2, children: [_jsx("planeGeometry", { args: [width, depth] }), _jsx("meshBasicMaterial", { color: highlightColor, transparent: true, opacity: 0.15, depthWrite: false })] })), _jsx(Text, { position: [0, textY, textZ], rotation: [textRotationX, 0, 0], fontSize: Math.max(6, Math.min(12, width / 3)), color: labelColor, anchorX: "center", anchorY: "middle", outlineWidth: 0.15, outlineColor: "#0f172a", children: dirName })] }));
|
|
606
580
|
}
|
|
607
581
|
let cameraApi = null;
|
|
608
582
|
export function resetCamera() {
|
|
@@ -1354,7 +1328,7 @@ function CityScene({ cityData, onBuildingHover, onBuildingClick, hoveredBuilding
|
|
|
1354
1328
|
// Focus color takes priority, then highlight layer color
|
|
1355
1329
|
const districtColor = (isFocused && buildingFocusColor) ? buildingFocusColor : highlightLayerColor;
|
|
1356
1330
|
return (_jsx(DistrictFloor, { district: district, centerOffset: centerOffset, opacity: 1, highlightColor: districtColor, growProgress: growProgress }, district.path));
|
|
1357
|
-
}), _jsx(InstancedBuildings, { buildings: cityData.buildings, centerOffset: centerOffset, onHover: onBuildingHover, onClick: onBuildingClick, hoveredIndex: hoveredIndex, selectedIndex: selectedIndex, growProgress: growProgress, animationConfig: animationConfig, heightScaling: heightScaling, linearScale: linearScale, flatPatterns: flatPatterns, staggerIndices: staggerIndices, focusDirectory: buildingFocusDirectory, highlightLayers: highlightLayers, isolationMode: isolationMode }), _jsx(BuildingIcons, { buildings: cityData.buildings, centerOffset: centerOffset, growProgress: growProgress, heightScaling: heightScaling, linearScale: linearScale, flatPatterns: flatPatterns, highlightLayers: highlightLayers, isolationMode: isolationMode, hasActiveHighlights: activeHighlights
|
|
1331
|
+
}), _jsx(InstancedBuildings, { buildings: cityData.buildings, centerOffset: centerOffset, onHover: onBuildingHover, onClick: onBuildingClick, hoveredIndex: hoveredIndex, selectedIndex: selectedIndex, growProgress: growProgress, animationConfig: animationConfig, heightScaling: heightScaling, linearScale: linearScale, flatPatterns: flatPatterns, staggerIndices: staggerIndices, focusDirectory: buildingFocusDirectory, highlightLayers: highlightLayers, isolationMode: isolationMode }), _jsx(BuildingIcons, { buildings: cityData.buildings, centerOffset: centerOffset, growProgress: growProgress, heightScaling: heightScaling, linearScale: linearScale, flatPatterns: flatPatterns, highlightLayers: highlightLayers, isolationMode: isolationMode, hasActiveHighlights: activeHighlights })] }));
|
|
1358
1332
|
}
|
|
1359
1333
|
/**
|
|
1360
1334
|
* FileCity3D - 3D visualization of codebase structure
|
package/package.json
CHANGED
|
@@ -769,9 +769,6 @@ interface BuildingIconsProps {
|
|
|
769
769
|
highlightLayers: HighlightLayer[];
|
|
770
770
|
isolationMode: IsolationMode;
|
|
771
771
|
hasActiveHighlights: boolean;
|
|
772
|
-
staggerIndices: number[];
|
|
773
|
-
springDuration: number;
|
|
774
|
-
staggerDelay: number;
|
|
775
772
|
}
|
|
776
773
|
|
|
777
774
|
// Individual animated icon component
|
|
@@ -783,8 +780,6 @@ interface AnimatedIconProps {
|
|
|
783
780
|
texture: THREE.Texture;
|
|
784
781
|
opacity: number;
|
|
785
782
|
growProgress: number;
|
|
786
|
-
staggerDelayMs: number;
|
|
787
|
-
springDuration: number;
|
|
788
783
|
}
|
|
789
784
|
|
|
790
785
|
function AnimatedIcon({
|
|
@@ -795,60 +790,33 @@ function AnimatedIcon({
|
|
|
795
790
|
texture,
|
|
796
791
|
opacity,
|
|
797
792
|
growProgress,
|
|
798
|
-
staggerDelayMs,
|
|
799
|
-
springDuration,
|
|
800
793
|
}: AnimatedIconProps) {
|
|
801
794
|
const meshRef = useRef<THREE.Mesh>(null);
|
|
802
|
-
const startTimeRef = useRef<number | null>(null);
|
|
803
795
|
const materialRef = useRef<THREE.MeshBasicMaterial>(null);
|
|
804
796
|
|
|
805
|
-
useFrame((
|
|
797
|
+
useFrame(() => {
|
|
806
798
|
if (!meshRef.current) return;
|
|
807
799
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
const currentTime = clock.elapsedTime * 1000;
|
|
813
|
-
const animStartTime = startTimeRef.current ?? currentTime;
|
|
814
|
-
|
|
815
|
-
// Calculate per-icon animation progress
|
|
816
|
-
const elapsed = currentTime - animStartTime - staggerDelayMs;
|
|
817
|
-
let animProgress = growProgress;
|
|
818
|
-
|
|
819
|
-
if (growProgress > 0 && elapsed >= 0) {
|
|
820
|
-
const t = Math.min(elapsed / springDuration, 1);
|
|
821
|
-
const eased = 1 - Math.pow(1 - t, 3);
|
|
822
|
-
animProgress = eased * growProgress;
|
|
823
|
-
} else if (growProgress > 0 && elapsed < 0) {
|
|
824
|
-
animProgress = 0;
|
|
825
|
-
}
|
|
826
|
-
|
|
800
|
+
// Icons track the global growProgress directly (no stagger)
|
|
801
|
+
// This keeps them in sync with the building heights
|
|
827
802
|
const minHeight = 0.3;
|
|
828
803
|
const baseOffset = 0.2;
|
|
829
|
-
const height =
|
|
804
|
+
const height = growProgress * targetHeight + minHeight;
|
|
830
805
|
const buildingTop = height + baseOffset;
|
|
831
806
|
|
|
832
|
-
// When flat (
|
|
833
|
-
// When grown (
|
|
807
|
+
// When flat (growProgress=0): icon lies flat at ground level
|
|
808
|
+
// When grown (growProgress=1): icon lies flat above building roof
|
|
834
809
|
const flatY = minHeight + baseOffset + 0.5;
|
|
835
|
-
const grownY = buildingTop +
|
|
836
|
-
const yPosition = flatY + (grownY - flatY) *
|
|
810
|
+
const grownY = buildingTop + 0.5;
|
|
811
|
+
const yPosition = flatY + (grownY - flatY) * growProgress;
|
|
837
812
|
|
|
838
813
|
meshRef.current.position.y = yPosition;
|
|
839
814
|
|
|
840
|
-
//
|
|
841
|
-
|
|
842
|
-
// Grown: 0 (facing forward)
|
|
843
|
-
const flatRotationX = -Math.PI / 2;
|
|
844
|
-
const grownRotationX = 0;
|
|
845
|
-
meshRef.current.rotation.x = flatRotationX + (grownRotationX - flatRotationX) * animProgress;
|
|
815
|
+
// Keep icon flat (facing up) at all times
|
|
816
|
+
meshRef.current.rotation.x = -Math.PI / 2;
|
|
846
817
|
|
|
847
818
|
if (materialRef.current) {
|
|
848
|
-
|
|
849
|
-
const minOpacity = 0.8;
|
|
850
|
-
const effectiveOpacity = minOpacity + (1 - minOpacity) * animProgress;
|
|
851
|
-
materialRef.current.opacity = opacity * effectiveOpacity;
|
|
819
|
+
materialRef.current.opacity = opacity;
|
|
852
820
|
}
|
|
853
821
|
});
|
|
854
822
|
|
|
@@ -883,14 +851,11 @@ function BuildingIcons({
|
|
|
883
851
|
highlightLayers,
|
|
884
852
|
isolationMode,
|
|
885
853
|
hasActiveHighlights,
|
|
886
|
-
staggerIndices,
|
|
887
|
-
springDuration,
|
|
888
|
-
staggerDelay,
|
|
889
854
|
}: BuildingIconsProps) {
|
|
890
855
|
// Pre-compute buildings with icons
|
|
891
856
|
const buildingsWithIcons = useMemo(() => {
|
|
892
857
|
return buildings
|
|
893
|
-
.map((building
|
|
858
|
+
.map((building) => {
|
|
894
859
|
const config = getConfigForFile(building);
|
|
895
860
|
if (!config.icon) return null;
|
|
896
861
|
|
|
@@ -900,17 +865,15 @@ function BuildingIcons({
|
|
|
900
865
|
const shouldHide = shouldDim && isolationMode === 'hide';
|
|
901
866
|
const shouldCollapse = shouldDim && isolationMode === 'collapse';
|
|
902
867
|
|
|
903
|
-
|
|
868
|
+
// Hide icons for buildings that are hidden or collapsed
|
|
869
|
+
if (shouldHide || shouldCollapse) return null;
|
|
904
870
|
|
|
905
871
|
const fullHeight = calculateBuildingHeight(building, heightScaling, linearScale, flatPatterns);
|
|
906
|
-
const targetHeight =
|
|
872
|
+
const targetHeight = fullHeight;
|
|
907
873
|
|
|
908
874
|
const x = building.position.x - centerOffset.x;
|
|
909
875
|
const z = building.position.z - centerOffset.z;
|
|
910
876
|
|
|
911
|
-
const staggerIndex = staggerIndices[index] ?? index;
|
|
912
|
-
const staggerDelayMs = staggerDelay * staggerIndex;
|
|
913
|
-
|
|
914
877
|
return {
|
|
915
878
|
building,
|
|
916
879
|
config,
|
|
@@ -918,7 +881,6 @@ function BuildingIcons({
|
|
|
918
881
|
z,
|
|
919
882
|
targetHeight,
|
|
920
883
|
shouldDim,
|
|
921
|
-
staggerDelayMs,
|
|
922
884
|
};
|
|
923
885
|
})
|
|
924
886
|
.filter(Boolean) as Array<{
|
|
@@ -928,7 +890,6 @@ function BuildingIcons({
|
|
|
928
890
|
z: number;
|
|
929
891
|
targetHeight: number;
|
|
930
892
|
shouldDim: boolean;
|
|
931
|
-
staggerDelayMs: number;
|
|
932
893
|
}>;
|
|
933
894
|
}, [
|
|
934
895
|
buildings,
|
|
@@ -939,15 +900,13 @@ function BuildingIcons({
|
|
|
939
900
|
heightScaling,
|
|
940
901
|
linearScale,
|
|
941
902
|
flatPatterns,
|
|
942
|
-
staggerIndices,
|
|
943
|
-
staggerDelay,
|
|
944
903
|
]);
|
|
945
904
|
|
|
946
905
|
// Icons are now always rendered (flat or grown)
|
|
947
906
|
return (
|
|
948
907
|
<>
|
|
949
908
|
{buildingsWithIcons.map(
|
|
950
|
-
({ building, config, x, z, targetHeight, shouldDim
|
|
909
|
+
({ building, config, x, z, targetHeight, shouldDim }) => {
|
|
951
910
|
const icon = config.icon!;
|
|
952
911
|
const texture = getIconTexture(icon.name, icon.color || '#ffffff');
|
|
953
912
|
if (!texture) return null;
|
|
@@ -969,8 +928,6 @@ function BuildingIcons({
|
|
|
969
928
|
texture={texture}
|
|
970
929
|
opacity={opacity}
|
|
971
930
|
growProgress={growProgress}
|
|
972
|
-
staggerDelayMs={staggerDelayMs}
|
|
973
|
-
springDuration={springDuration}
|
|
974
931
|
/>
|
|
975
932
|
);
|
|
976
933
|
},
|
|
@@ -1015,8 +972,8 @@ function DistrictFloor({ district, centerOffset, highlightColor, growProgress }:
|
|
|
1015
972
|
const grownY = 1.5;
|
|
1016
973
|
const textY = flatY + (grownY - flatY) * growProgress;
|
|
1017
974
|
|
|
1018
|
-
const flatZ =
|
|
1019
|
-
const grownZ = depth / 2 + 2; //
|
|
975
|
+
const flatZ = depth / 2 - 6; // Near bottom of district when flat, with padding
|
|
976
|
+
const grownZ = depth / 2 + 2; // Just outside edge when grown
|
|
1020
977
|
const textZ = flatZ + (grownZ - flatZ) * growProgress;
|
|
1021
978
|
|
|
1022
979
|
return (
|
|
@@ -1035,20 +992,19 @@ function DistrictFloor({ district, centerOffset, highlightColor, growProgress }:
|
|
|
1035
992
|
</mesh>
|
|
1036
993
|
)}
|
|
1037
994
|
|
|
1038
|
-
{
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
)}
|
|
995
|
+
{/* Always show directory name label */}
|
|
996
|
+
<Text
|
|
997
|
+
position={[0, textY, textZ]}
|
|
998
|
+
rotation={[textRotationX, 0, 0]}
|
|
999
|
+
fontSize={Math.max(6, Math.min(12, width / 3))}
|
|
1000
|
+
color={labelColor}
|
|
1001
|
+
anchorX="center"
|
|
1002
|
+
anchorY="middle"
|
|
1003
|
+
outlineWidth={0.15}
|
|
1004
|
+
outlineColor="#0f172a"
|
|
1005
|
+
>
|
|
1006
|
+
{dirName}
|
|
1007
|
+
</Text>
|
|
1052
1008
|
</group>
|
|
1053
1009
|
);
|
|
1054
1010
|
}
|
|
@@ -2140,9 +2096,6 @@ function CityScene({
|
|
|
2140
2096
|
highlightLayers={highlightLayers}
|
|
2141
2097
|
isolationMode={isolationMode}
|
|
2142
2098
|
hasActiveHighlights={activeHighlights}
|
|
2143
|
-
staggerIndices={staggerIndices}
|
|
2144
|
-
springDuration={springDuration}
|
|
2145
|
-
staggerDelay={animationConfig.staggerDelay || 15}
|
|
2146
2099
|
/>
|
|
2147
2100
|
</>
|
|
2148
2101
|
);
|