added error handling in asset move controls and rotate controls

This commit is contained in:
2025-09-22 14:42:07 +05:30
parent eb4ef77599
commit 7c3e9e2588
4 changed files with 119 additions and 88 deletions

View File

@@ -9,7 +9,7 @@ import useAisleResponseHandler from "../responseHandler/useAisleResponseHandler"
function BuilderResponses() {
const { assetStore } = useSceneContext();
const { getAssetById } = assetStore();
const { getAssetById, movedObjects, initialStates, updateAsset, resetAsset, setInitialState } = assetStore();
const { selectedAisle, setSelectedAisle, selectedWall, setSelectedWall } = useBuilderStore();
const { builderSocket } = useSocketStore();
const { addAssetToScene, updateAssetInScene, removeAssetFromScene } = useAssetResponseHandler();
@@ -23,6 +23,17 @@ function BuilderResponses() {
builderSocket.on("v1:model-asset:response:add", (data: any) => {
if (!data.message || !data.data) {
setInitialState({});
setTimeout(() => {
Object.entries(initialStates).forEach(([key, initialState]) => {
updateAsset(key, {
position: initialState.position,
rotation: initialState.rotation,
});
resetAsset(key);
});
}, 50);
echo.error(`Error adding or updating asset`);
return;
}
@@ -41,6 +52,7 @@ function BuilderResponses() {
};
addAssetToScene(model, () => {
setInitialState({});
echo.log(`Added asset: ${model.modelName}`);
});
} else if (data.message === "Model updated successfully" && data.data) {
@@ -58,10 +70,22 @@ function BuilderResponses() {
};
updateAssetInScene(model, () => {
setInitialState({});
echo.log(`Updated asset: ${model.modelName}`);
});
} else {
removeAssetFromScene(data.data.modelUuid, () => {
setInitialState({});
setTimeout(() => {
Object.entries(initialStates).forEach(([key, initialState]) => {
updateAsset(key, {
position: initialState.position,
rotation: initialState.rotation,
});
resetAsset(key);
});
}, 50);
echo.error(`Error adding or updating asset: ${data?.data?.modelName}`);
});
}
@@ -158,7 +182,7 @@ function BuilderResponses() {
builderSocket.off("v1:model-asset:response:delete");
}
};
}, [builderSocket]);
}, [builderSocket, movedObjects, initialStates]);
//#endregion
//#region WallAsset

View File

@@ -41,6 +41,8 @@ function MoveControls3D({ boundingBoxRef }: any) {
setDuplicatedObjects,
rotatedObjects,
setRotatedObjects,
initialStates,
setInitialState,
} = assetStore();
const { updateAssetInScene } = useAssetResponseHandler();
const { selectedVersion } = versionStore();
@@ -48,8 +50,6 @@ function MoveControls3D({ boundingBoxRef }: any) {
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 [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 { contextAction, setContextAction } = useContextActionStore();
@@ -204,16 +204,15 @@ function MoveControls3D({ boundingBoxRef }: any) {
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],
position: initialState.position,
rotation: initialState.rotation,
});
movedObject.position.copy(initialState.position);
movedObject.position.set(initialState.position[0], initialState.position[1], initialState.position[2]);
if (initialState.rotation) {
movedObject.rotation.copy(initialState.rotation);
movedObject.rotation.set(initialState.rotation[0], initialState.rotation[1], initialState.rotation[2]);
}
}
});
@@ -231,16 +230,14 @@ function MoveControls3D({ boundingBoxRef }: any) {
const initialState = initialStates[movedObject.uuid];
if (!initialState) return;
const positionArray: [number, number, number] = [initialState.position.x, initialState.position.y, initialState.position.z];
updateAsset(modelUuid, {
position: positionArray,
rotation: [initialState.rotation?.x || 0, initialState.rotation?.y || 0, initialState.rotation?.z || 0],
position: initialState.position,
rotation: initialState.rotation,
});
movedObject.position.copy(initialState.position);
movedObject.position.set(initialState.position[0], initialState.position[1], initialState.position[2]);
if (initialState.rotation) {
movedObject.rotation.copy(initialState.rotation);
movedObject.rotation.set(initialState.rotation[0], initialState.rotation[1], initialState.rotation[2]);
}
setAxisConstraint(null);
@@ -287,10 +284,14 @@ function MoveControls3D({ boundingBoxRef }: any) {
movedObjects.forEach((movedAsset: THREE.Object3D) => {
if (movedAsset.userData.modelUuid) {
const initialPosition = initialPositions[movedAsset.userData.modelUuid];
const initialState = initialStates[movedAsset.userData.modelUuid];
const offsetState = initialStates[movedObjects[0].uuid];
if (initialPosition) {
const relativeOffset = new THREE.Vector3().subVectors(initialPosition, initialPositions[movedObjects[0].uuid]);
if (initialState.position && offsetState.position) {
const relativeOffset = new THREE.Vector3().subVectors(
new THREE.Vector3(initialState.position[0], initialState.position[1], initialState.position[2]),
new THREE.Vector3(offsetState.position[0], offsetState.position[1], offsetState.position[2])
);
const model = scene.getObjectByProperty("uuid", movedAsset.userData.modelUuid);
const newPosition = new THREE.Vector3().addVectors(baseNewPosition, relativeOffset);
@@ -317,19 +318,18 @@ function MoveControls3D({ boundingBoxRef }: any) {
});
const moveAssets = () => {
const states: Record<string, { position: THREE.Vector3; rotation?: THREE.Euler }> = {};
const states: Record<string, { position: [number, number, number]; rotation: [number, number, number] }> = {};
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,
position: asset.position.toArray(),
rotation: [asset.rotation.x, asset.rotation.y, asset.rotation.z],
};
positions[asset.uuid] = new THREE.Vector3().copy(asset.position);
});
setInitialStates(states);
setInitialPositions(positions);
setInitialState(states);
raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
@@ -357,15 +357,15 @@ function MoveControls3D({ boundingBoxRef }: any) {
const model = scene.getObjectByProperty("uuid", movedAsset.userData.modelUuid);
if (!asset || !model) return;
const position = new THREE.Vector3().copy(model.position);
const initialState = initialStates[movedAsset.uuid];
const initialState = initialStates[assetUuid];
if (initialState) {
assetsToUpdate.push({
type: "Asset",
assetData: {
...asset,
position: [initialState.position.x, initialState.position.y, initialState.position.z],
rotation: [initialState.rotation?.x || 0, initialState.rotation?.y || 0, initialState.rotation?.z || 0],
position: initialState.position,
rotation: initialState.rotation,
},
newData: {
...asset,

View File

@@ -27,6 +27,7 @@ function RotateControls3D() {
const { push3D } = undoRedo3DStore();
const {
updateAsset,
getAssetById,
rotatedObjects,
setRotatedObjects,
selectedAssets,
@@ -37,13 +38,13 @@ function RotateControls3D() {
setPastedObjects,
duplicatedObjects,
setDuplicatedObjects,
initialStates,
setInitialState,
} = assetStore();
const { updateAssetInScene } = useAssetResponseHandler();
const { selectedVersion } = versionStore();
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 [isIndividualRotating, setIsIndividualRotating] = useState(false);
const prevPointerPosition = useRef<THREE.Vector2 | null>(null);
@@ -168,7 +169,7 @@ function RotateControls3D() {
canvasElement.removeEventListener("keydown", onKeyDown);
canvasElement?.removeEventListener("keyup", onKeyUp);
};
}, [camera, scene, toggleView, toolMode, selectedAssets, rotatedObjects, pastedObjects, duplicatedObjects, movedObjects, keyEvent, initialPositions, initialRotations, isIndividualRotating]);
}, [camera, scene, toggleView, toolMode, selectedAssets, rotatedObjects, pastedObjects, duplicatedObjects, movedObjects, keyEvent, initialStates, isIndividualRotating]);
useEffect(() => {
if (activeModule !== "builder" || toolMode !== "cursor" || toggleView) {
@@ -179,55 +180,47 @@ function RotateControls3D() {
const resetToInitialRotations = useCallback(() => {
setTimeout(() => {
rotatedObjects.forEach((obj: THREE.Object3D) => {
const uuid = obj.uuid;
if (obj.userData.modelUuid) {
const initialRotation = initialRotations[uuid];
const initialPosition = initialPositions[uuid];
rotatedObjects.forEach((rotatedObject: THREE.Object3D) => {
if (rotatedObject.userData.modelUuid && initialStates[rotatedObject.uuid]) {
const initialState = initialStates[rotatedObject.uuid];
if (initialRotation && initialPosition) {
const rotationArray: [number, number, number] = [initialRotation.x, initialRotation.y, initialRotation.z];
const positionArray: [number, number, number] = [initialPosition.x, initialPosition.y, initialPosition.z];
updateAsset(rotatedObject.userData.modelUuid, {
position: initialState.position,
rotation: initialState.rotation,
});
updateAsset(obj.userData.modelUuid, {
rotation: rotationArray,
position: positionArray,
});
obj.rotation.copy(initialRotation);
obj.position.copy(initialPosition);
rotatedObject.position.set(initialState.position[0], initialState.position[1], initialState.position[2]);
if (initialState.rotation) {
rotatedObject.rotation.set(initialState.rotation[0], initialState.rotation[1], initialState.rotation[2]);
}
}
});
}, 50);
}, [rotatedObjects, initialRotations, initialPositions, updateAsset]);
}, [rotatedObjects, initialStates, updateAsset]);
const resetToInitialRotation = useCallback(
(modelUuid: string) => {
setTimeout(() => {
const obj = rotatedObjects.find((o: THREE.Object3D) => o.userData.modelUuid === modelUuid);
const rotatedObject = rotatedObjects.find((o: THREE.Object3D) => o.userData.modelUuid === modelUuid);
if (!obj) return;
if (!rotatedObject) return;
const uuid = obj.uuid;
const initialRotation = initialRotations[uuid];
const initialPosition = initialPositions[uuid];
if (initialRotation && initialPosition) {
const rotationArray: [number, number, number] = [initialRotation.x, initialRotation.y, initialRotation.z];
const positionArray: [number, number, number] = [initialPosition.x, initialPosition.y, initialPosition.z];
const initialState = initialStates[rotatedObject.uuid];
if (initialState) {
updateAsset(modelUuid, {
rotation: rotationArray,
position: positionArray,
position: initialState.position,
rotation: initialState.rotation,
});
obj.rotation.copy(initialRotation);
obj.position.copy(initialPosition);
rotatedObject.position.set(initialState.position[0], initialState.position[1], initialState.position[2]);
if (initialState.rotation) {
rotatedObject.rotation.set(initialState.rotation[0], initialState.rotation[1], initialState.rotation[2]);
}
}
}, 50);
},
[rotatedObjects, initialRotations, initialPositions, updateAsset]
[rotatedObjects, initialStates, updateAsset]
);
useFrame(() => {
@@ -273,7 +266,7 @@ function RotateControls3D() {
});
const rotateAssets = useCallback(() => {
const rotations: Record<string, THREE.Euler> = {};
const states: Record<string, { position: [number, number, number]; rotation: [number, number, number] }> = {};
const positions: Record<string, THREE.Vector3> = {};
const box = new THREE.Box3();
@@ -282,13 +275,15 @@ function RotateControls3D() {
box.getCenter(center);
rotationCenter.current = center;
selectedAssets.forEach((obj: THREE.Object3D) => {
rotations[obj.uuid] = new THREE.Euler().copy(obj.rotation);
positions[obj.uuid] = new THREE.Vector3().copy(obj.position);
selectedAssets.forEach((asset: THREE.Object3D) => {
states[asset.uuid] = {
position: asset.position.toArray(),
rotation: [asset.rotation.x, asset.rotation.y, asset.rotation.z],
};
positions[asset.uuid] = new THREE.Vector3().copy(asset.position);
});
setInitialRotations(rotations);
setInitialPositions(positions);
setInitialState(states);
raycaster.setFromCamera(pointer, camera);
@@ -304,22 +299,24 @@ function RotateControls3D() {
const undoActions: UndoRedo3DAction[] = [];
const assetsToUpdate: AssetData[] = [];
rotatedObjects.forEach((obj: THREE.Object3D) => {
if (obj?.userData.modelUuid) {
const asset = assetStore.getState().getAssetById(obj.userData.modelUuid);
rotatedObjects.forEach((rotatedObject: THREE.Object3D) => {
if (rotatedObject) {
const assetUuid = rotatedObject.userData.modelUuid;
const asset = getAssetById(assetUuid);
if (!asset) return;
const initialState = initialStates[assetUuid];
const rotationArray: [number, number, number] = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
const rotationArray: [number, number, number] = [rotatedObject.rotation.x, rotatedObject.rotation.y, rotatedObject.rotation.z];
const positionArray: [number, number, number] = [obj.position.x, obj.position.y, obj.position.z];
const positionArray: [number, number, number] = [rotatedObject.position.x, rotatedObject.position.y, rotatedObject.position.z];
if (initialRotations[obj.uuid] && initialPositions[obj.uuid]) {
if (initialState) {
assetsToUpdate.push({
type: "Asset",
assetData: {
...asset,
position: [initialPositions[obj.uuid].x, initialPositions[obj.uuid].y, initialPositions[obj.uuid].z],
rotation: [initialRotations[obj.uuid].x, initialRotations[obj.uuid].y, initialRotations[obj.uuid].z],
position: initialState.position,
rotation: initialState.rotation,
},
newData: {
...asset,
@@ -331,28 +328,28 @@ function RotateControls3D() {
}
const newFloorItem: Types.FloorItemType = {
modelUuid: obj.userData.modelUuid,
modelName: obj.userData.modelName,
assetId: obj.userData.assetId,
modelUuid: rotatedObject.userData.modelUuid,
modelName: rotatedObject.userData.modelName,
assetId: rotatedObject.userData.assetId,
position: positionArray,
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
rotation: { x: rotatedObject.rotation.x, y: rotatedObject.rotation.y, z: rotatedObject.rotation.z },
isLocked: false,
isVisible: true,
};
if (obj.userData.eventData) {
const eventData = eventStore.getState().getEventByModelUuid(obj.userData.modelUuid);
const productData = productStore.getState().getEventByModelUuid(productStore.getState().selectedProduct.productUuid, obj.userData.modelUuid);
if (rotatedObject.userData.eventData) {
const eventData = eventStore.getState().getEventByModelUuid(rotatedObject.userData.modelUuid);
const productData = productStore.getState().getEventByModelUuid(productStore.getState().selectedProduct.productUuid, rotatedObject.userData.modelUuid);
if (eventData) {
eventStore.getState().updateEvent(obj.userData.modelUuid, {
eventStore.getState().updateEvent(rotatedObject.userData.modelUuid, {
position: positionArray,
rotation: rotationArray,
});
}
if (productData) {
const event = productStore.getState().updateEvent(productStore.getState().selectedProduct.productUuid, obj.userData.modelUuid, {
const event = productStore.getState().updateEvent(productStore.getState().selectedProduct.productUuid, rotatedObject.userData.modelUuid, {
position: positionArray,
rotation: rotationArray,
});
@@ -371,7 +368,7 @@ function RotateControls3D() {
modelName: newFloorItem.modelName,
assetId: newFloorItem.assetId,
position: newFloorItem.position,
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
rotation: { x: rotatedObject.rotation.x, y: rotatedObject.rotation.y, z: rotatedObject.rotation.z },
isLocked: false,
isVisible: true,
socketId: builderSocket?.id,
@@ -388,7 +385,7 @@ function RotateControls3D() {
modelName: newFloorItem.modelName,
assetId: newFloorItem.assetId,
position: newFloorItem.position,
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
rotation: { x: rotatedObject.rotation.x, y: rotatedObject.rotation.y, z: rotatedObject.rotation.z },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || "",
@@ -397,7 +394,7 @@ function RotateControls3D() {
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error rotating asset: ${newFloorItem.modelUuid}`);
resetToInitialRotations();
resetToInitialRotation(newFloorItem.modelUuid);
clearSelection();
return;
}
@@ -421,13 +418,14 @@ function RotateControls3D() {
});
} else {
echo.error(`Error rotating asset: ${newFloorItem.modelUuid}`);
resetToInitialRotations();
resetToInitialRotation(newFloorItem.modelUuid);
clearSelection();
}
})
.catch(() => {
echo.error(`Error rotating asset: ${newFloorItem.modelUuid}`);
resetToInitialRotations();
resetToInitialRotation(newFloorItem.modelUuid);
clearSelection();
});
} else {
@@ -462,7 +460,7 @@ function RotateControls3D() {
setIsRotating(false);
setIsIndividualRotating(false);
clearSelection();
}, [rotatedObjects, eventStore, productStore, updateBackend, projectId, updateAsset, organization, builderSocket, selectedVersion, userId, initialPositions, initialRotations]);
}, [rotatedObjects, eventStore, productStore, updateBackend, projectId, updateAsset, organization, builderSocket, selectedVersion, userId, initialStates]);
const clearSelection = () => {
setPastedObjects([]);

View File

@@ -10,6 +10,7 @@ interface AssetsStore {
copiedObjects: Object3D[];
pastedObjects: Object3D[];
duplicatedObjects: Object3D[];
initialStates: Record<string, { position: [number, number, number]; rotation: [number, number, number] }>;
// Asset CRUD operations
addAsset: (asset: Asset) => void;
@@ -25,6 +26,7 @@ interface AssetsStore {
setCopiedObjects: (objects: Object3D[]) => Object3D[];
setPastedObjects: (objects: Object3D[]) => Object3D[];
setDuplicatedObjects: (objects: Object3D[]) => Object3D[];
setInitialState: (initialStates: Record<string, { position: [number, number, number]; rotation: [number, number, number] }>) => void;
// Asset properties
setName: (modelUuid: string, newName: string) => void;
@@ -64,6 +66,7 @@ export const createAssetStore = () => {
copiedObjects: [],
pastedObjects: [],
duplicatedObjects: [],
initialStates: {},
// Asset CRUD operations
addAsset: (asset) => {
@@ -155,6 +158,12 @@ export const createAssetStore = () => {
return objects;
},
setInitialState: (initialStates) => {
set((state) => {
state.initialStates = initialStates;
});
},
// Asset properties
setName: (modelUuid, newName) => {
set((state) => {