Dwinzo_dev/app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx

103 lines
3.6 KiB
TypeScript
Raw Normal View History

2025-04-21 06:23:42 +00:00
import { Line } from "@react-three/drei";
import { useMemo } from "react";
import * as THREE from "three";
import { useSelectedAssets } from "../../../../store/builder/store";
2025-04-21 06:23:42 +00:00
interface BoundingBoxProps {
boundingBoxRef?: any;
isPerAsset?: boolean;
}
const getBoxLines = (min: THREE.Vector3, max: THREE.Vector3) => [
[min.x, min.y, min.z], [max.x, min.y, min.z],
[max.x, min.y, min.z], [max.x, max.y, min.z],
[max.x, max.y, min.z], [min.x, max.y, min.z],
[min.x, max.y, min.z], [min.x, min.y, min.z],
2025-04-21 06:23:42 +00:00
[min.x, min.y, max.z], [max.x, min.y, max.z],
[max.x, min.y, max.z], [max.x, max.y, max.z],
[max.x, max.y, max.z], [min.x, max.y, max.z],
[min.x, max.y, max.z], [min.x, min.y, max.z],
2025-04-21 06:23:42 +00:00
[min.x, min.y, min.z], [min.x, min.y, max.z],
[max.x, min.y, min.z], [max.x, min.y, max.z],
[max.x, max.y, min.z], [max.x, max.y, max.z],
[min.x, max.y, min.z], [min.x, max.y, max.z],
];
2025-04-21 06:23:42 +00:00
const BoundingBox = ({ boundingBoxRef, isPerAsset = true }: BoundingBoxProps) => {
const { selectedAssets } = useSelectedAssets();
const savedTheme: string = localStorage.getItem("theme") || "light";
2025-04-21 06:23:42 +00:00
const boxes = useMemo(() => {
if (selectedAssets.length === 0) return [];
2025-04-21 06:23:42 +00:00
if (isPerAsset) {
return selectedAssets.map((obj: any) => {
const box = new THREE.Box3().setFromObject(obj.clone());
const size = new THREE.Vector3();
const center = new THREE.Vector3();
box.getSize(size);
box.getCenter(center);
2025-04-21 06:23:42 +00:00
const halfSize = size.clone().multiplyScalar(0.5);
const min = center.clone().sub(halfSize);
const max = center.clone().add(halfSize);
2025-04-21 06:23:42 +00:00
return {
points: getBoxLines(min, max),
position: center.toArray(),
size: size.toArray(),
};
});
} else {
const box = new THREE.Box3();
selectedAssets.forEach((obj: any) => box.expandByObject(obj.clone()));
const size = new THREE.Vector3();
const center = new THREE.Vector3();
box.getSize(size);
box.getCenter(center);
2025-04-21 06:23:42 +00:00
const halfSize = size.clone().multiplyScalar(0.5);
const min = center.clone().sub(halfSize);
const max = center.clone().add(halfSize);
2025-04-21 06:23:42 +00:00
return [
{
points: getBoxLines(min, max),
position: center.toArray(),
size: size.toArray(),
},
];
}
}, [selectedAssets, isPerAsset]);
2025-04-21 06:23:42 +00:00
return (
<>
{boxes.map((box: any, index: number) => (
<group key={index} name="SelectionGroupBoundingBoxLine">
<Line
name="SelectionGroupBoundingBox"
depthWrite={false}
points={box.points}
color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"}
lineWidth={2.7}
segments
/>
<mesh
name="SelectionGroupBoundingLine"
ref={index === 0 ? boundingBoxRef : null}
visible={false}
position={box.position}
>
<boxGeometry args={box.size} />
2025-04-21 06:23:42 +00:00
<meshBasicMaterial />
</mesh>
</group>
))}
2025-04-21 06:23:42 +00:00
</>
);
};
export default BoundingBox;