Merge remote-tracking branch 'origin/main-dev' into main-demo

This commit is contained in:
2025-08-14 16:19:39 +05:30
7 changed files with 215 additions and 52 deletions

View File

@@ -9,6 +9,7 @@ import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { handleAssetPositionSnap } from "./functions/handleAssetPositionSnap";
// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
@@ -35,11 +36,16 @@ const DuplicationControls3D = ({
const { selectedVersion } = selectedVersionStore();
const { userId, organization } = getUserData();
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("");
const [axisConstraint, setAxisConstraint] = useState<"x" | "z" | null>(null);
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({});
const [isDuplicating, setIsDuplicating] = useState(false);
const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ left: false, right: false, });
const { contextAction, setContextAction } = useContextActionStore()
const fineMoveBaseRef = useRef<THREE.Vector3 | null>(null);
const lastPointerPositionRef = useRef<THREE.Vector3 | null>(null);
const wasShiftHeldRef = useRef(false);
const calculateDragOffset = useCallback((point: THREE.Object3D, hitPoint: THREE.Vector3) => {
const pointPosition = new THREE.Vector3().copy(point.position);
@@ -85,11 +91,33 @@ const DuplicationControls3D = ({
removeAsset(obj.userData.modelUuid);
});
}
setKeyEvent("");
};
const onKeyDown = (event: KeyboardEvent) => {
const keyCombination = detectModifierKeys(event);
if (isDuplicating && duplicatedObjects.length > 0) {
if (event.key.toLowerCase() === 'x') {
setAxisConstraint(prev => prev === 'x' ? null : 'x');
event.preventDefault();
return;
}
if (event.key.toLowerCase() === 'z') {
setAxisConstraint(prev => prev === 'z' ? null : 'z');
event.preventDefault();
return;
}
}
if (keyCombination !== keyEvent) {
if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") {
setKeyEvent(keyCombination);
} else {
setKeyEvent("");
}
}
if (keyCombination === "Ctrl+D" && movedObjects.length === 0 && rotatedObjects.length === 0) {
duplicateSelection();
}
@@ -102,11 +130,34 @@ const DuplicationControls3D = ({
}
};
const onKeyUp = (event: KeyboardEvent) => {
const keyCombination = detectModifierKeys(event);
if (keyCombination === "") {
setKeyEvent("");
} else if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") {
setKeyEvent(keyCombination);
}
if (duplicatedObjects[0] && keyEvent !== "" && keyCombination === '') {
const intersectionPoint = new THREE.Vector3();
raycaster.setFromCamera(pointer, camera);
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
const model = scene.getObjectByProperty("uuid", duplicatedObjects[0].userData.modelUuid);
if (model) {
const newOffset = calculateDragOffset(model, intersectionPoint);
setDragOffset(newOffset);
}
}
}
};
if (!toggleView) {
canvasElement.addEventListener("pointerdown", onPointerDown);
canvasElement.addEventListener("pointermove", onPointerMove);
canvasElement.addEventListener("pointerup", onPointerUp);
canvasElement.addEventListener("keydown", onKeyDown);
canvasElement.addEventListener("keyup", onKeyUp);
}
return () => {
@@ -114,8 +165,9 @@ const DuplicationControls3D = ({
canvasElement.removeEventListener("pointermove", onPointerMove);
canvasElement.removeEventListener("pointerup", onPointerUp);
canvasElement.removeEventListener("keydown", onKeyDown);
canvasElement.addEventListener("keyup", onKeyUp);
};
}, [assets, camera, controls, scene, toggleView, selectedAssets, duplicatedObjects, movedObjects, socket, rotatedObjects]);
}, [assets, camera, controls, scene, toggleView, selectedAssets, duplicatedObjects, movedObjects, socket, rotatedObjects, keyEvent]);
useFrame(() => {
if (!isDuplicating || duplicatedObjects.length === 0) return;
@@ -135,7 +187,9 @@ const DuplicationControls3D = ({
}
if (dragOffset) {
const adjustedHit = new THREE.Vector3().addVectors(intersectionPoint, dragOffset);
const rawBasePosition = new THREE.Vector3().addVectors(intersectionPoint, dragOffset);
const model = scene.getObjectByProperty("uuid", duplicatedObjects[0].userData.modelUuid);
const baseNewPosition = handleAssetPositionSnap({ rawBasePosition, intersectionPoint, model, axisConstraint, keyEvent, fineMoveBaseRef, lastPointerPositionRef, wasShiftHeldRef });
duplicatedObjects.forEach((duplicatedObject: THREE.Object3D) => {
if (duplicatedObject.userData.modelUuid) {
@@ -149,7 +203,7 @@ const DuplicationControls3D = ({
);
const model = scene.getObjectByProperty("uuid", duplicatedObject.userData.modelUuid);
const newPosition = new THREE.Vector3().addVectors(adjustedHit, relativeOffset);
const newPosition = new THREE.Vector3().addVectors(baseNewPosition, relativeOffset);
const positionArray: [number, number, number] = [newPosition.x, newPosition.y, newPosition.z];
if (model) {
@@ -162,6 +216,21 @@ const DuplicationControls3D = ({
}
});
useEffect(() => {
if (duplicatedObjects.length > 0) {
const intersectionPoint = new THREE.Vector3();
raycaster.setFromCamera(pointer, camera);
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
const model = scene.getObjectByProperty("uuid", duplicatedObjects[0].userData.modelUuid);
if (model) {
const newOffset = calculateDragOffset(model, intersectionPoint);
setDragOffset(newOffset);
}
}
}
}, [axisConstraint, camera, duplicatedObjects])
const duplicateSelection = useCallback(() => {
if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
const positions: Record<string, THREE.Vector3> = {};
@@ -593,6 +662,7 @@ const DuplicationControls3D = ({
setSelectedAssets([]);
setIsDuplicating(false);
setDragOffset(null);
setAxisConstraint(null);
};
return null;