moveControls and other controls altered

This commit is contained in:
2025-07-18 14:14:34 +05:30
parent 0b9f23ba4f
commit c309af135d
9 changed files with 634 additions and 485 deletions

View File

@@ -1,5 +1,5 @@
import * as THREE from "three";
import { useEffect, useMemo, useRef, useState } from "react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { useSelectedAssets, useSocketStore, useToggleView, } from "../../../../../store/builder/store";
import * as Types from "../../../../../types/world/worldTypes";
@@ -22,7 +22,6 @@ function MoveControls3D({
setpastedObjects,
duplicatedObjects,
setDuplicatedObjects,
selectionGroup,
rotatedObjects,
setRotatedObjects,
boundingBoxRef,
@@ -39,11 +38,19 @@ function MoveControls3D({
const { userId, organization } = getUserData();
const { projectId } = useParams();
const { assetStore, eventStore, productStore } = useSceneContext();
const { updateAsset } = assetStore();
const AssetGroup = useRef<THREE.Group | undefined>(undefined);
const { updateAsset, setPosition, getAssetById } = assetStore();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({});
const [initialStates, setInitialStates] = useState<Record<string, { position: THREE.Vector3; rotation?: THREE.Euler; }>>({});
const [isMoving, setIsMoving] = useState(false);
const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({
left: false,
right: false,
});
const updateBackend = (
productName: string,
productUuid: string,
@@ -65,22 +72,10 @@ function MoveControls3D({
const canvasElement = gl.domElement;
canvasElement.tabIndex = 0;
const itemsGroup: any = scene.getObjectByName("Asset Group");
AssetGroup.current = itemsGroup;
if (!AssetGroup.current) {
console.error("Asset Group not found in the scene.");
return;
}
let isMoving = false;
const onPointerDown = () => {
isMoving = false;
};
let isPointerMoving = false;
const onPointerMove = () => {
isMoving = true;
isPointerMoving = true;
};
const onKeyUp = (event: KeyboardEvent) => {
@@ -91,21 +86,25 @@ function MoveControls3D({
}
};
const onPointerDown = (event: PointerEvent) => {
isPointerMoving = false;
if (event.button === 0) mouseButtonsDown.current.left = true;
if (event.button === 2) mouseButtonsDown.current.right = true;
};
const onPointerUp = (event: PointerEvent) => {
if (!isMoving && movedObjects.length > 0 && event.button === 0) {
if (event.button === 0) mouseButtonsDown.current.left = false;
if (event.button === 2) mouseButtonsDown.current.right = false;
if (!isPointerMoving && movedObjects.length > 0 && event.button === 0) {
event.preventDefault();
placeMovedAssets();
}
if (!isMoving && movedObjects.length > 0 && event.button === 2) {
if (!isPointerMoving && movedObjects.length > 0 && event.button === 2) {
event.preventDefault();
resetToInitialPositions();
clearSelection();
movedObjects.forEach((asset: any) => {
if (AssetGroup.current) {
AssetGroup.current.attach(asset);
}
});
setMovedObjects([]);
}
setKeyEvent("");
@@ -131,14 +130,8 @@ function MoveControls3D({
if (keyCombination === "ESCAPE") {
event.preventDefault();
resetToInitialPositions();
clearSelection();
movedObjects.forEach((asset: any) => {
if (AssetGroup.current) {
AssetGroup.current.attach(asset);
}
});
setMovedObjects([]);
}
};
@@ -158,118 +151,154 @@ function MoveControls3D({
canvasElement.removeEventListener("keydown", onKeyDown);
canvasElement?.removeEventListener("keyup", onKeyUp);
};
}, [camera, controls, scene, toggleView, selectedAssets, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent,]);
}, [camera, controls, scene, toggleView, selectedAssets, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent]);
let moveSpeed = keyEvent === "Ctrl" || "Ctrl+Shift" ? 1 : 0.25;
const calculateDragOffset = useCallback((point: THREE.Object3D, hitPoint: THREE.Vector3) => {
const pointPosition = new THREE.Vector3().copy(point.position);
return new THREE.Vector3().subVectors(pointPosition, hitPoint);
}, []);
const resetToInitialPositions = useCallback(() => {
setTimeout(() => {
movedObjects.forEach((movedObject: THREE.Object3D) => {
if (movedObject.userData.modelUuid && initialStates[movedObject.uuid]) {
const initialState = initialStates[movedObject.uuid];
const positionArray: [number, number, number] = [
initialState.position.x,
initialState.position.y,
initialState.position.z
];
updateAsset(movedObject.userData.modelUuid, {
position: positionArray,
rotation: [
initialState.rotation?.x || 0,
initialState.rotation?.y || 0,
initialState.rotation?.z || 0
],
});
movedObject.position.copy(initialState.position);
if (initialState.rotation) {
movedObject.rotation.copy(initialState.rotation);
}
}
});
}, 0)
}, [movedObjects, initialStates, updateAsset]);
useFrame(() => {
if (movedObjects.length > 0) {
const intersectionPoint = new THREE.Vector3();
raycaster.setFromCamera(pointer, camera);
let point = raycaster.ray.intersectPlane(plane, intersectionPoint);
const floorsGroup = scene.getObjectByName("Floors-Group") as Types.Group | null;
const floorChildren = floorsGroup?.children ?? [];
const floorIntersections = raycaster.intersectObjects([...floorChildren], true);
const intersectedFloor = floorIntersections.find((intersect) => intersect.object.name.includes("Floor"));
if (!isMoving || movedObjects.length === 0) return;
if (intersectedFloor && selectedAssets.length === 1) {
if (intersectedFloor.object.userData.floorUuid) {
point = new THREE.Vector3(intersectedFloor.point.x, intersectedFloor.object.userData.floorDepth, intersectedFloor.point.z);
const intersectionPoint = new THREE.Vector3();
raycaster.setFromCamera(pointer, camera);
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
if (mouseButtonsDown.current.left || mouseButtonsDown.current.right) {
if (movedObjects[0]) {
const newOffset = calculateDragOffset(movedObjects[0], intersectionPoint);
setDragOffset(newOffset);
}
return;
}
if (point) {
let targetX = point.x;
let targetY = point.y;
let targetZ = point.z;
if (dragOffset) {
const baseNewPosition = new THREE.Vector3().addVectors(intersectionPoint, dragOffset);
let moveSpeed = keyEvent === "Shift" || "Ctrl+Shift" ? 0.25 : 1;
if (keyEvent === "Ctrl") {
targetX = snapControls(targetX, "Ctrl");
targetZ = snapControls(targetZ, "Ctrl");
baseNewPosition.x = snapControls(baseNewPosition.x, "Ctrl");
baseNewPosition.z = snapControls(baseNewPosition.z, "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 {
// }
movedObjects.forEach((movedAsset: THREE.Object3D) => {
if (movedAsset.userData.modelUuid) {
const initialPosition = initialPositions[movedAsset.userData.modelUuid];
if (initialPosition) {
const relativeOffset = new THREE.Vector3().subVectors(
initialPosition,
initialPositions[movedObjects[0].uuid]
);
const newPosition = new THREE.Vector3().addVectors(baseNewPosition, relativeOffset);
const positionArray: [number, number, number] = [newPosition.x, newPosition.y, newPosition.z];
setPosition(movedAsset.userData.modelUuid, positionArray);
}
}
});
const position = new THREE.Vector3();
if (boundingBoxRef.current) {
boundingBoxRef.current.getWorldPosition(position);
selectionGroup.current.position.lerp(
new THREE.Vector3(
targetX - (position.x - selectionGroup.current.position.x),
targetY - (position.y - selectionGroup.current.position.y),
targetZ - (position.z - selectionGroup.current.position.z)
),
moveSpeed
);
} else {
const box = new THREE.Box3();
movedObjects.forEach((obj: THREE.Object3D) =>
box.expandByObject(obj)
);
movedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj));
const center = new THREE.Vector3();
box.getCenter(center);
selectionGroup.current.position.lerp(
new THREE.Vector3(
targetX - (center.x - selectionGroup.current.position.x),
selectionGroup.current.position.y,
targetZ - (center.z - selectionGroup.current.position.z)
),
moveSpeed
);
}
}
}
});
const moveAssets = () => {
setMovedObjects(selectedAssets);
selectedAssets.forEach((asset: any) => {
selectionGroup.current.attach(asset);
const states: Record<string, { position: THREE.Vector3; rotation?: THREE.Euler; }> = {};
const positions: Record<string, THREE.Vector3> = {};
selectedAssets.forEach((asset: THREE.Object3D) => {
states[asset.uuid] = {
position: new THREE.Vector3().copy(asset.position),
rotation: asset.rotation ? new THREE.Euler().copy(asset.rotation) : undefined
};
positions[asset.uuid] = new THREE.Vector3().copy(asset.position);
});
setInitialStates(states);
setInitialPositions(positions);
raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit && selectedAssets[0]) {
const offset = calculateDragOffset(selectedAssets[0], hit);
setDragOffset(offset);
}
setMovedObjects(selectedAssets);
setIsMoving(true);
};
const placeMovedAssets = () => {
if (movedObjects.length === 0) return;
movedObjects.forEach(async (obj: THREE.Object3D) => {
if (obj && AssetGroup.current) {
let worldPosition = new THREE.Vector3();
obj.getWorldPosition(worldPosition);
if (worldPosition.y < 0) {
worldPosition.y = 0;
}
selectionGroup.current.remove(obj);
obj.position.copy(worldPosition);
movedObjects.forEach(async (movedAsset: THREE.Object3D) => {
if (movedAsset) {
const assetUuid = movedAsset.userData.modelUuid;
const asset = getAssetById(assetUuid);
if (!asset) return;
const newFloorItem: Types.FloorItemType = {
modelUuid: obj.userData.modelUuid,
modelName: obj.userData.modelName,
assetId: obj.userData.assetId,
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
modelUuid: movedAsset.userData.modelUuid,
modelName: movedAsset.userData.modelName,
assetId: movedAsset.userData.assetId,
position: asset.position,
rotation: { x: movedAsset.rotation.x, y: movedAsset.rotation.y, z: movedAsset.rotation.z },
isLocked: false,
isVisible: true,
};
if (obj.userData.eventData) {
const eventData = eventStore.getState().getEventByModelUuid(obj.userData.modelUuid);
const productData = productStore.getState().getEventByModelUuid(selectedProduct.productUuid, obj.userData.modelUuid);
if (movedAsset.userData.eventData) {
const eventData = eventStore.getState().getEventByModelUuid(movedAsset.userData.modelUuid);
const productData = productStore.getState().getEventByModelUuid(selectedProduct.productUuid, movedAsset.userData.modelUuid);
if (eventData) {
eventStore.getState().updateEvent(obj.userData.modelUuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
eventStore.getState().updateEvent(movedAsset.userData.modelUuid, {
position: asset.position,
rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z],
});
}
@@ -278,10 +307,10 @@ function MoveControls3D({
.getState()
.updateEvent(
selectedProduct.productUuid,
obj.userData.modelUuid,
movedAsset.userData.modelUuid,
{
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
position: asset.position,
rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z],
}
);
@@ -298,9 +327,9 @@ function MoveControls3D({
}
}
updateAsset(obj.userData.modelUuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
updateAsset(movedAsset.userData.modelUuid, {
position: asset.position,
rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z],
});
//REST
@@ -324,7 +353,7 @@ function MoveControls3D({
modelName: newFloorItem.modelName,
assetId: newFloorItem.assetId,
position: newFloorItem.position,
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
rotation: { x: movedAsset.rotation.x, y: movedAsset.rotation.y, z: movedAsset.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
@@ -333,22 +362,16 @@ function MoveControls3D({
userId
};
// console.log('data: ', data);
socket.emit("v1:model-asset:add", data);
AssetGroup.current.add(obj);
}
});
echo.success("Object moved!");
setIsMoving(false);
clearSelection();
};
const clearSelection = () => {
selectionGroup.current.children = [];
selectionGroup.current.position.set(0, 0, 0);
selectionGroup.current.rotation.set(0, 0, 0);
setpastedObjects([]);
setDuplicatedObjects([]);
setMovedObjects([]);
@@ -365,4 +388,4 @@ function MoveControls3D({
);
}
export default MoveControls3D;
export default MoveControls3D;