refactor: Update asset properties and selection controls for improved functionality using shift click functionality

This commit is contained in:
Jerald-Golden-B 2025-05-29 12:55:17 +05:30
parent e26de7e651
commit e72854d514
6 changed files with 66 additions and 12 deletions

View File

@ -48,7 +48,7 @@ const AssetProperties: React.FC = () => {
return ( return (
<div className="asset-properties-container"> <div className="asset-properties-container">
{/* Name */} {/* Name */}
<div className="header">{selectedFloorItem.userData.name}</div> <div className="header">{selectedFloorItem.userData.modelName}</div>
<section> <section>
{objectPosition.x && objectPosition.z && {objectPosition.x && objectPosition.z &&
<PositionInput <PositionInput

View File

@ -201,8 +201,6 @@ function Model({ asset }: { readonly asset: Asset }) {
} }
} }
const handleContextMenu = (asset: Asset, evt: ThreeEvent<MouseEvent>) => { const handleContextMenu = (asset: Asset, evt: ThreeEvent<MouseEvent>) => {
if (activeTool === "cursor" && subModule === 'simulations') { if (activeTool === "cursor" && subModule === 'simulations') {
if (asset.modelUuid) { if (asset.modelUuid) {

View File

@ -75,8 +75,9 @@ const BoundingBox = ({ boundingBoxRef, isPerAsset = true }: BoundingBoxProps) =>
return ( return (
<> <>
{boxes.map((box: any, index: number) => ( {boxes.map((box: any, index: number) => (
<group key={index}> <group key={index} name="SelectionGroupBoundingBoxLine">
<Line <Line
name="SelectionGroupBoundingBox"
depthWrite={false} depthWrite={false}
points={box.points} points={box.points}
color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"} color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"}
@ -84,6 +85,7 @@ const BoundingBox = ({ boundingBoxRef, isPerAsset = true }: BoundingBoxProps) =>
segments segments
/> />
<mesh <mesh
name="SelectionGroupBoundingLine"
ref={index === 0 ? boundingBoxRef : null} ref={index === 0 ? boundingBoxRef : null}
visible={false} visible={false}
position={box.position} position={box.position}

View File

@ -18,7 +18,7 @@ import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useAssetsStore } from "../../../../store/builder/useAssetStore"; import { useAssetsStore } from "../../../../store/builder/useAssetStore";
const SelectionControls: React.FC = () => { const SelectionControls: React.FC = () => {
const { camera, controls, gl, scene, pointer } = useThree(); const { camera, controls, gl, scene, raycaster, pointer } = useThree();
const selectionGroup = useRef() as Types.RefGroup; const selectionGroup = useRef() as Types.RefGroup;
const { toggleView } = useToggleView(); const { toggleView } = useToggleView();
const { selectedAssets, setSelectedAssets } = useSelectedAssets(); const { selectedAssets, setSelectedAssets } = useSelectedAssets();
@ -39,10 +39,13 @@ const SelectionControls: React.FC = () => {
const canvasElement = gl.domElement; const canvasElement = gl.domElement;
canvasElement.tabIndex = 0; canvasElement.tabIndex = 0;
let isDragging = false;
let isLeftMouseDown = false;
let isSelecting = false; let isSelecting = false;
let isRightClick = false; let isRightClick = false;
let rightClickMoved = false; let rightClickMoved = false;
let isCtrlSelecting = false; let isCtrlSelecting = false;
let isShiftSelecting = false;
const helper = new SelectionHelper(gl); const helper = new SelectionHelper(gl);
@ -53,6 +56,9 @@ const SelectionControls: React.FC = () => {
} else if (event.button === 0) { } else if (event.button === 0) {
isSelecting = false; isSelecting = false;
isCtrlSelecting = event.ctrlKey; isCtrlSelecting = event.ctrlKey;
isShiftSelecting = event.shiftKey;
isLeftMouseDown = true;
isDragging = false;
if (event.ctrlKey && duplicatedObjects.length === 0) { if (event.ctrlKey && duplicatedObjects.length === 0) {
if (controls) (controls as any).enabled = false; if (controls) (controls as any).enabled = false;
selectionBox.startPoint.set(pointer.x, pointer.y, 0); selectionBox.startPoint.set(pointer.x, pointer.y, 0);
@ -64,6 +70,9 @@ const SelectionControls: React.FC = () => {
if (isRightClick) { if (isRightClick) {
rightClickMoved = true; rightClickMoved = true;
} }
if (isLeftMouseDown) {
isDragging = true;
}
isSelecting = true; isSelecting = true;
if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) { if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) {
selectionBox.endPoint.set(pointer.x, pointer.y, 0); selectionBox.endPoint.set(pointer.x, pointer.y, 0);
@ -71,7 +80,7 @@ const SelectionControls: React.FC = () => {
}; };
const onPointerUp = (event: PointerEvent) => { const onPointerUp = (event: PointerEvent) => {
if (event.button === 2) { if (event.button === 2 && !event.ctrlKey && !event.shiftKey) {
isRightClick = false; isRightClick = false;
if (!rightClickMoved) { if (!rightClickMoved) {
clearSelection(); clearSelection();
@ -85,10 +94,59 @@ const SelectionControls: React.FC = () => {
if (event.ctrlKey && duplicatedObjects.length === 0) { if (event.ctrlKey && duplicatedObjects.length === 0) {
selectAssets(); selectAssets();
} }
} else if (!isSelecting && selectedAssets.length > 0 && ((pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) || event.button !== 0)) { } else if (!isSelecting && selectedAssets.length > 0 && ((!event.ctrlKey && !event.shiftKey && pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) || event.button !== 0)) {
clearSelection(); clearSelection();
helper.enabled = true; helper.enabled = true;
isCtrlSelecting = false; isCtrlSelecting = false;
} else if (controls) {
(controls as any).enabled = true;
}
if (!isDragging && isLeftMouseDown && isShiftSelecting && event.shiftKey) {
isShiftSelecting = false;
isLeftMouseDown = false;
isDragging = false;
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(scene.children, true)
.filter(
(intersect) =>
!intersect.object.name.includes("Roof") &&
!intersect.object.name.includes("MeasurementReference") &&
!intersect.object.name.includes("agv-collider") &&
!intersect.object.name.includes("SelectionGroup") &&
!intersect.object.name.includes("selectionAssetGroup") &&
!intersect.object.name.includes("SelectionGroupBoundingBoxLine") &&
!intersect.object.name.includes("SelectionGroupBoundingBox") &&
!intersect.object.name.includes("SelectionGroupBoundingLine") &&
intersect.object.type !== "GridHelper"
);
if (intersects.length > 0) {
const intersect = intersects[0];
const intersectObject = intersect.object;
let currentObject: THREE.Object3D | null = intersectObject;
while (currentObject) {
if (currentObject.userData.modelUuid) {
break;
}
currentObject = currentObject.parent || null;
}
if (currentObject) {
const updatedSelections = new Set(selectedAssets);
if (updatedSelections.has(currentObject)) {
updatedSelections.delete(currentObject);
} else {
updatedSelections.add(currentObject);
}
const selected = Array.from(updatedSelections);
setSelectedAssets(selected);
}
}
} }
}; };

View File

@ -51,7 +51,7 @@ const MeasurementTool = () => {
!intersect.object.name.includes("Roof") && !intersect.object.name.includes("Roof") &&
!intersect.object.name.includes("MeasurementReference") && !intersect.object.name.includes("MeasurementReference") &&
!intersect.object.name.includes("agv-collider") && !intersect.object.name.includes("agv-collider") &&
!(intersect.object.type === "GridHelper") intersect.object.type !== "GridHelper"
); );
if (intersects.length > 0) { if (intersects.length > 0) {

View File

@ -35,10 +35,6 @@ function Products() {
} }
}, [comparisonProduct]) }, [comparisonProduct])
useEffect(() => {
console.log(selectedProduct);
}, [selectedProduct])
useEffect(() => { useEffect(() => {
const email = localStorage.getItem('email') const email = localStorage.getItem('email')
const organization = (email!.split("@")[1]).split(".")[0]; const organization = (email!.split("@")[1]).split(".")[0];