rotational snap added

This commit is contained in:
2025-08-14 18:13:28 +05:30
parent 922085ec6c
commit a8c6f8d80a
3 changed files with 117 additions and 27 deletions

View File

@@ -9,6 +9,8 @@ import { useProductContext } from "../../../../simulation/products/productContex
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import { handleAssetRotationSnap } from "./functions/handleAssetRotationSnap";
// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
@@ -23,7 +25,6 @@ function RotateControls3D({
setDuplicatedObjects
}: any) {
const { camera, gl, scene, pointer, raycaster } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const { toggleView } = useToggleView();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
@@ -38,15 +39,16 @@ function RotateControls3D({
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("");
const [initialRotations, setInitialRotations] = useState<Record<string, THREE.Euler>>({});
const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({});
const [isRotating, setIsRotating] = useState(false);
const prevPointerPosition = useRef<THREE.Vector2 | null>(null);
const rotationCenter = useRef<THREE.Vector3 | null>(null);
const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({
left: false,
right: false,
});
const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ left: false, right: false, });
const snapBaseRef = useRef<number | null>(null);
const prevRotationRef = useRef<number | null>(null);
const wasShiftHeldRef = useRef(false);
const updateBackend = useCallback((
productName: string,
@@ -98,6 +100,8 @@ function RotateControls3D({
};
const onKeyDown = (event: KeyboardEvent) => {
const keyCombination = detectModifierKeys(event);
if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || movedObjects.length > 0) return;
if (event.key.toLowerCase() === "r") {
@@ -105,6 +109,15 @@ function RotateControls3D({
rotateAssets();
}
}
if (keyCombination !== keyEvent) {
if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") {
setKeyEvent(keyCombination);
} else {
setKeyEvent("");
}
}
if (event.key.toLowerCase() === "escape") {
event.preventDefault();
resetToInitialRotations();
@@ -113,11 +126,24 @@ function RotateControls3D({
}
};
const onKeyUp = (event: KeyboardEvent) => {
const keyCombination = detectModifierKeys(event);
if (keyCombination === "") {
setKeyEvent("");
} else if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") {
setKeyEvent(keyCombination);
}
const currentPointer = new THREE.Vector2(pointer.x, pointer.y);
prevPointerPosition.current = currentPointer.clone();
};
if (!toggleView) {
canvasElement.addEventListener("pointerdown", onPointerDown);
canvasElement.addEventListener("pointermove", onPointerMove);
canvasElement.addEventListener("pointerup", onPointerUp);
canvasElement.addEventListener("keydown", onKeyDown);
canvasElement?.addEventListener("keyup", onKeyUp);
}
return () => {
@@ -125,8 +151,9 @@ function RotateControls3D({
canvasElement.removeEventListener("pointermove", onPointerMove);
canvasElement.removeEventListener("pointerup", onPointerUp);
canvasElement.removeEventListener("keydown", onKeyDown);
canvasElement?.removeEventListener("keyup", onKeyUp);
};
}, [camera, scene, toggleView, selectedAssets, rotatedObjects, pastedObjects, duplicatedObjects, movedObjects]);
}, [camera, scene, toggleView, selectedAssets, rotatedObjects, pastedObjects, duplicatedObjects, movedObjects, keyEvent]);
const resetToInitialRotations = useCallback(() => {
rotatedObjects.forEach((obj: THREE.Object3D) => {
@@ -154,26 +181,27 @@ function RotateControls3D({
useFrame(() => {
if (!isRotating || rotatedObjects.length === 0) return;
const intersectionPoint = new THREE.Vector3();
raycaster.setFromCamera(pointer, camera);
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
const currentPointer = new THREE.Vector2(pointer.x, pointer.y);
if (mouseButtonsDown.current.left || mouseButtonsDown.current.right) {
if (point) {
prevPointerPosition.current = new THREE.Vector2(point.x, point.z);
}
prevPointerPosition.current = currentPointer.clone();
return;
}
if (point && prevPointerPosition.current && rotationCenter.current) {
if (prevPointerPosition.current && rotationCenter.current) {
const center = rotationCenter.current;
const deltaX = currentPointer.x - prevPointerPosition.current.x;
const currentAngle = Math.atan2(point.z - center.z, point.x - center.x);
const prevAngle = Math.atan2(
prevPointerPosition.current.y - center.z,
prevPointerPosition.current.x - center.x
);
const angleDelta = prevAngle - currentAngle;
const rawAngleDelta = deltaX;
const angleDelta = handleAssetRotationSnap({
currentRotation: rotatedObjects[0].rotation,
rotationDelta: rawAngleDelta,
keyEvent,
snapBaseRef,
prevRotationRef,
wasShiftHeldRef
});
const rotationMatrix = new THREE.Matrix4().makeRotationY(angleDelta);
@@ -186,7 +214,7 @@ function RotateControls3D({
}
});
prevPointerPosition.current = new THREE.Vector2(point.x, point.z);
prevPointerPosition.current = currentPointer.clone();
}
});
@@ -208,17 +236,13 @@ function RotateControls3D({
setInitialRotations(rotations);
setInitialPositions(positions);
const intersectionPoint = new THREE.Vector3();
raycaster.setFromCamera(pointer, camera);
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (point) {
prevPointerPosition.current = new THREE.Vector2(point.x, point.z);
}
prevPointerPosition.current = new THREE.Vector2(pointer.x, pointer.y);
setRotatedObjects(selectedAssets);
setIsRotating(true);
}, [selectedAssets, camera, pointer, raycaster, plane]);
}, [selectedAssets, camera, pointer, raycaster]);
const placeRotatedAssets = useCallback(() => {
if (rotatedObjects.length === 0) return;