added snap function for ctrl and ctrl+shift key
This commit is contained in:
parent
e6fc9642df
commit
ef2baacf55
|
@ -1,7 +1,7 @@
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useEffect, useMemo, useRef } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
|
import { useFloorItems, useSelectedAssets, useSocketStore, useStartSimulation, useToggleView } from "../../../../store/store";
|
||||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
|
@ -10,6 +10,7 @@ import { useEventsStore } from "../../../../store/simulation/useEventsStore";
|
||||||
import { useProductStore } from "../../../../store/simulation/useProductStore";
|
import { useProductStore } from "../../../../store/simulation/useProductStore";
|
||||||
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
|
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
|
||||||
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
|
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
|
||||||
|
import { snapControls } from "../../../../utils/handleSnap";
|
||||||
|
|
||||||
function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
|
function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
|
||||||
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
||||||
|
@ -21,6 +22,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||||
const { floorItems, setFloorItems } = useFloorItems();
|
const { floorItems, setFloorItems } = useFloorItems();
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const itemsData = useRef<Types.FloorItems>([]);
|
const itemsData = useRef<Types.FloorItems>([]);
|
||||||
|
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("")
|
||||||
|
|
||||||
const email = localStorage.getItem('email')
|
const email = localStorage.getItem('email')
|
||||||
const organization = (email!.split("@")[1]).split(".")[0];
|
const organization = (email!.split("@")[1]).split(".")[0];
|
||||||
|
@ -54,6 +56,15 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||||
const onPointerMove = () => {
|
const onPointerMove = () => {
|
||||||
isMoving = true;
|
isMoving = true;
|
||||||
};
|
};
|
||||||
|
const onKeyUp = (event: KeyboardEvent) => {
|
||||||
|
// When any modifier is released, reset snap
|
||||||
|
const isModifierKey =
|
||||||
|
event.key === "Control" || event.key === "Shift";
|
||||||
|
|
||||||
|
if (isModifierKey) {
|
||||||
|
setKeyEvent("");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const onPointerUp = (event: PointerEvent) => {
|
const onPointerUp = (event: PointerEvent) => {
|
||||||
if (!isMoving && movedObjects.length > 0 && event.button === 0) {
|
if (!isMoving && movedObjects.length > 0 && event.button === 0) {
|
||||||
|
@ -75,18 +86,28 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||||
setMovedObjects([]);
|
setMovedObjects([]);
|
||||||
itemsData.current = [];
|
itemsData.current = [];
|
||||||
}
|
}
|
||||||
|
setKeyEvent("")
|
||||||
};
|
};
|
||||||
|
|
||||||
const onKeyDown = (event: KeyboardEvent) => {
|
const onKeyDown = (event: KeyboardEvent) => {
|
||||||
const keyCombination = detectModifierKeys(event);
|
const keyCombination = detectModifierKeys(event);
|
||||||
|
|
||||||
if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0) return;
|
if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0) return;
|
||||||
|
|
||||||
|
if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") {
|
||||||
|
// update state here
|
||||||
|
setKeyEvent(keyCombination)
|
||||||
|
} else {
|
||||||
|
setKeyEvent("")
|
||||||
|
}
|
||||||
|
|
||||||
if (keyCombination === "G") {
|
if (keyCombination === "G") {
|
||||||
if (selectedAssets.length > 0) {
|
if (selectedAssets.length > 0) {
|
||||||
moveAssets();
|
moveAssets();
|
||||||
itemsData.current = floorItems.filter((item: { modelUuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modelUuid));
|
itemsData.current = floorItems.filter((item: { modelUuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modelUuid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyCombination === "ESCAPE") {
|
if (keyCombination === "ESCAPE") {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
@ -109,6 +130,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||||
canvasElement.addEventListener("pointermove", onPointerMove);
|
canvasElement.addEventListener("pointermove", onPointerMove);
|
||||||
canvasElement.addEventListener("pointerup", onPointerUp);
|
canvasElement.addEventListener("pointerup", onPointerUp);
|
||||||
canvasElement.addEventListener("keydown", onKeyDown);
|
canvasElement.addEventListener("keydown", onKeyDown);
|
||||||
|
canvasElement?.addEventListener("keyup", onKeyUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -116,12 +138,11 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||||
canvasElement.removeEventListener("pointermove", onPointerMove);
|
canvasElement.removeEventListener("pointermove", onPointerMove);
|
||||||
canvasElement.removeEventListener("pointerup", onPointerUp);
|
canvasElement.removeEventListener("pointerup", onPointerUp);
|
||||||
canvasElement.removeEventListener("keydown", onKeyDown);
|
canvasElement.removeEventListener("keydown", onKeyDown);
|
||||||
|
canvasElement?.removeEventListener("keyup", onKeyUp);
|
||||||
};
|
};
|
||||||
}, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects]);
|
}, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent]);
|
||||||
|
|
||||||
const gridSize = 0.25;
|
let moveSpeed = keyEvent === "Ctrl" || "Ctrl+Shift" ? 1 : 0.25;
|
||||||
const moveSpeed = 0.25;
|
|
||||||
const isGridSnap = false;
|
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
if (movedObjects.length > 0) {
|
if (movedObjects.length > 0) {
|
||||||
|
@ -132,10 +153,17 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||||
if (point) {
|
if (point) {
|
||||||
let targetX = point.x;
|
let targetX = point.x;
|
||||||
let targetZ = point.z;
|
let targetZ = point.z;
|
||||||
|
if (keyEvent === "Ctrl") {
|
||||||
|
targetX = snapControls(targetX, "Ctrl");
|
||||||
|
targetZ = snapControls(targetZ, "Ctrl");
|
||||||
|
} else if (keyEvent === "Ctrl+Shift") {
|
||||||
|
targetX = snapControls(targetX, "Ctrl+Shift");
|
||||||
|
targetZ = snapControls(targetZ, "Ctrl+Shift");
|
||||||
|
} else if (keyEvent === "Shift") {
|
||||||
|
targetX = snapControls(targetX, "Shift");
|
||||||
|
targetZ = snapControls(targetZ, "Shift");
|
||||||
|
} else {
|
||||||
|
|
||||||
if (isGridSnap) {
|
|
||||||
targetX = Math.round(point.x / gridSize) * gridSize;
|
|
||||||
targetZ = Math.round(point.z / gridSize) * gridSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const position = new THREE.Vector3();
|
const position = new THREE.Vector3();
|
||||||
|
@ -278,6 +306,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||||
setMovedObjects([]);
|
setMovedObjects([]);
|
||||||
setRotatedObjects([]);
|
setRotatedObjects([]);
|
||||||
setSelectedAssets([]);
|
setSelectedAssets([]);
|
||||||
|
setKeyEvent("")
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,65 +1,22 @@
|
||||||
import { useEffect } from "react";
|
export function snapControls(value: number, event: string): number {
|
||||||
import { detectModifierKeys } from "./shortcutkeys/detectModifierKeys";
|
const CTRL_DISTANCE = 1; // Snap to whole numbers when Ctrl is pressed
|
||||||
|
const SHIFT_DISTANCE = 0.01; // Snap to half-step increments when Shift is pressed
|
||||||
|
const CTRL_SHIFT_DISTANCE = 0.1; // Snap to fine increments when both Ctrl and Shift are pressed
|
||||||
|
|
||||||
// Define the props expected by the component
|
switch (event) {
|
||||||
type SnapControlsProps = {
|
case "Ctrl":
|
||||||
x_point: number; // X-coordinate value to snap
|
return Math.round(value / CTRL_DISTANCE) * CTRL_DISTANCE;
|
||||||
z_point: number; // Z-coordinate value to snap
|
|
||||||
};
|
|
||||||
|
|
||||||
const SnapControls: React.FC<SnapControlsProps> = ({ x_point, z_point }) => {
|
case "Shift":
|
||||||
useEffect(() => {
|
return Math.round(value / SHIFT_DISTANCE) * SHIFT_DISTANCE;
|
||||||
// Handler function for keypress events
|
|
||||||
const handleKeyPress = (event: KeyboardEvent) => {
|
|
||||||
// Detect which modifier keys (Ctrl, Shift, etc.) are currently pressed
|
|
||||||
const keyCombination = detectModifierKeys(event);
|
|
||||||
|
|
||||||
// Define the snapping distances
|
case "Ctrl+Shift":
|
||||||
const CTRL_DISTANCE = 1; // Coarse snapping when Ctrl is pressed
|
const base = Math.floor(value / CTRL_DISTANCE) * CTRL_DISTANCE;
|
||||||
const SHIFT_DISTANCE = 0.01; // Fine snapping when Shift is pressed
|
const offset =
|
||||||
|
Math.round((value - base) / CTRL_SHIFT_DISTANCE) * CTRL_SHIFT_DISTANCE;
|
||||||
|
return base + offset;
|
||||||
|
|
||||||
// Prevent default behavior to avoid unintended side effects
|
default:
|
||||||
event.preventDefault();
|
return value; // No snapping if no modifier key is pressed
|
||||||
|
}
|
||||||
// Create new coordinates to apply snapping to
|
}
|
||||||
let newX = x_point;
|
|
||||||
let newZ = z_point;
|
|
||||||
|
|
||||||
// Check for modifier key combinations and apply appropriate snapping logic
|
|
||||||
if (keyCombination) {
|
|
||||||
if (keyCombination === "Ctrl") {
|
|
||||||
// Snap to nearest integer unit
|
|
||||||
newX = Math.round(x_point / CTRL_DISTANCE) * CTRL_DISTANCE;
|
|
||||||
newZ = Math.round(z_point / CTRL_DISTANCE) * CTRL_DISTANCE;
|
|
||||||
return { newX, newZ };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyCombination === "Ctrl+Shift") {
|
|
||||||
// Snap to nearest small unit (0.01)
|
|
||||||
newX = Math.round(x_point / SHIFT_DISTANCE) * SHIFT_DISTANCE;
|
|
||||||
newZ = Math.round(z_point / SHIFT_DISTANCE) * SHIFT_DISTANCE;
|
|
||||||
return { newX, newZ };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyCombination === "Shift") {
|
|
||||||
// Incorrect snapping logic — rounding the point and multiplying by small value
|
|
||||||
newX = Math.round(x_point) * SHIFT_DISTANCE;
|
|
||||||
newZ = Math.round(z_point) * SHIFT_DISTANCE;
|
|
||||||
return { newX, newZ };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Attach keydown event listener when the component mounts
|
|
||||||
window.addEventListener("keydown", handleKeyPress);
|
|
||||||
|
|
||||||
// Clean up the event listener when the component unmounts
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener("keydown", handleKeyPress);
|
|
||||||
};
|
|
||||||
}, []); // Empty dependency array means this effect runs once on mount
|
|
||||||
|
|
||||||
return null; // This component doesn’t render anything
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SnapControls;
|
|
||||||
|
|
Loading…
Reference in New Issue