diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx index ee53dc8..b78bf2d 100644 --- a/app/src/modules/builder/asset/assetsGroup.tsx +++ b/app/src/modules/builder/asset/assetsGroup.tsx @@ -16,6 +16,7 @@ import { useLeftData, useTopData } from "../../../store/visualization/useZone3DW import { getUserData } from "../../../functions/getUserData"; import { useSceneContext } from "../../scene/sceneContext"; import { useBuilderStore } from "../../../store/builder/useBuilderStore"; +import useAssetResponseHandler from "./responseHandler/useAssetResponseHandler"; const gltfLoaderWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js", import.meta.url)); @@ -26,8 +27,9 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) { const { setLoadingProgress } = useLoadingProgress(); const { assetStore, eventStore, versionStore } = useSceneContext(); const { selectedVersion } = versionStore(); - const { setAssets, addAsset, clearAssets } = assetStore(); + const { setAssets, clearAssets } = assetStore(); const { addEvent, clearEvents } = eventStore(); + const { addAssetToScene } = useAssetResponseHandler(); const { setSelectedFloorAsset } = useBuilderStore(); const { selectedItem, setSelectedItem } = useSelectedItem(); const { projectId } = useParams(); @@ -347,7 +349,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) { pointer.x = (event.clientX / window.innerWidth) * 2 - 1; pointer.y = -(event.clientY / window.innerHeight) * 2 + 1; - addAssetModel(scene, raycaster, camera, pointer, builderSocket, selectedItem, setSelectedItem, addEvent, addAsset, plane, loader, selectedVersion, projectId, userId); + addAssetModel(scene, raycaster, camera, pointer, builderSocket, selectedItem, setSelectedItem, addEvent, addAssetToScene, plane, loader, selectedVersion, projectId, userId); } }; diff --git a/app/src/modules/builder/asset/functions/addAssetModel.ts b/app/src/modules/builder/asset/functions/addAssetModel.ts index 706ea86..43384d7 100644 --- a/app/src/modules/builder/asset/functions/addAssetModel.ts +++ b/app/src/modules/builder/asset/functions/addAssetModel.ts @@ -18,7 +18,7 @@ async function addAssetModel( selectedItem: any, setSelectedItem: any, addEvent: (event: EventsSchema) => void, - addAsset: (asset: Asset) => void, + addAssetToScene: (asset: Asset, callback?: () => void) => void, plane: Types.RefMesh, loader: GLTFLoader, selectedVersion?: Version | null, @@ -68,7 +68,7 @@ async function addAssetModel( } const cachedModel = THREE.Cache.get(selectedItem.id); if (cachedModel) { - handleModelLoad(cachedModel, intersectPoint!, selectedItem, addEvent, addAsset, builderSocket, selectedVersion?.versionId || "", projectId, userId); + handleModelLoad(cachedModel, intersectPoint!, selectedItem, addEvent, addAssetToScene, builderSocket, selectedVersion?.versionId || "", projectId, userId); return; } else { const cachedModelBlob = await retrieveGLTF(selectedItem.id); @@ -78,14 +78,14 @@ async function addAssetModel( URL.revokeObjectURL(blobUrl); THREE.Cache.remove(blobUrl); THREE.Cache.add(selectedItem.id, gltf); - handleModelLoad(gltf, intersectPoint!, selectedItem, addEvent, addAsset, builderSocket, selectedVersion?.versionId || "", projectId, userId); + handleModelLoad(gltf, intersectPoint!, selectedItem, addEvent, addAssetToScene, builderSocket, selectedVersion?.versionId || "", projectId, userId); }); } else { loader.load(`${url_Backend_dwinzo}/api/v2/AssetFile/${selectedItem.id}`, async (gltf) => { const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v2/AssetFile/${selectedItem.id}`).then((res) => res.blob()); await storeGLTF(selectedItem.id, modelBlob); THREE.Cache.add(selectedItem.id, gltf); - await handleModelLoad(gltf, intersectPoint!, selectedItem, addEvent, addAsset, builderSocket, selectedVersion?.versionId || "", projectId, userId); + await handleModelLoad(gltf, intersectPoint!, selectedItem, addEvent, addAssetToScene, builderSocket, selectedVersion?.versionId || "", projectId, userId); }); } } @@ -102,7 +102,7 @@ async function handleModelLoad( intersectPoint: THREE.Vector3, selectedItem: any, addEvent: (event: EventsSchema) => void, - addAsset: (asset: Asset) => void, + addAssetToScene: (asset: Asset, callback?: () => void) => void, builderSocket: Socket | null, versionId: string, projectId?: string, @@ -447,27 +447,39 @@ async function handleModelLoad( isVisible: true, versionId: versionId, projectId: projectId, - }); + }) + .then((data) => { + if (!data.message) { + echo.error(`Error adding asset: ${newFloorItem.modelUuid}`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + eventData: data.data.eventData, + }; + + addAssetToScene(model, () => { + echo.log(`Added asset: ${model.modelName}`); + }); + } + }) + .catch(() => { + echo.error(`Error adding asset: ${newFloorItem.modelUuid}`); + }); } else { // SOCKET builderSocket.emit("v1:model-asset:add", completeData); } - - const asset: Asset = { - modelUuid: completeData.modelUuid, - modelName: completeData.modelName, - assetId: completeData.assetId, - position: completeData.position, - rotation: [completeData.rotation.x, completeData.rotation.y, completeData.rotation.z] as [number, number, number], - isLocked: completeData.isLocked, - isCollidable: false, - isVisible: completeData.isVisible, - opacity: 1, - eventData: completeData.eventData, - }; - - addAsset(asset); } else { const data = { organization, @@ -497,26 +509,38 @@ async function handleModelLoad( isVisible: true, versionId: versionId, projectId: projectId, - }); + }) + .then((data) => { + if (!data.message) { + echo.error(`Error adding asset: ${newFloorItem.modelUuid}`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + }; + + addAssetToScene(model, () => { + echo.log(`Added asset: ${model.modelUuid}`); + }); + } + }) + .catch(() => { + echo.error(`Error adding asset: ${newFloorItem.modelUuid}`); + }); } else { // SOCKET builderSocket.emit("v1:model-asset:add", data); } - - const asset = { - modelUuid: data.modelUuid, - modelName: data.modelName, - assetId: data.assetId, - position: data.position, - rotation: [data.rotation.x, data.rotation.y, data.rotation.z] as [number, number, number], - isLocked: data.isLocked, - isCollidable: false, - isVisible: data.isVisible, - opacity: 1, - }; - - addAsset(asset); } } diff --git a/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts b/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts index 1d3efe3..6331ac7 100644 --- a/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts +++ b/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts @@ -12,6 +12,7 @@ import { getUserData } from "../../../../../../functions/getUserData"; import { useLeftData, useTopData } from "../../../../../../store/visualization/useZone3DWidgetStore"; import { useSelectedAsset } from "../../../../../../store/simulation/useSimulationStore"; import { useBuilderStore } from "../../../../../../store/builder/useBuilderStore"; +import useAssetResponseHandler from "../../../responseHandler/useAssetResponseHandler"; import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi"; import { deleteFloorAssetApi } from "../../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorAssetApi"; @@ -23,15 +24,15 @@ export function useModelEventHandlers({ boundingBox, groupRef, asset }: { boundi const { toggleView } = useToggleView(); const { subModule } = useSubModuleStore(); const { builderSocket } = useSocketStore(); - const { eventStore, productStore, assetStore, undoRedo3DStore, versionStore } = useSceneContext(); + const { eventStore, productStore, undoRedo3DStore, versionStore } = useSceneContext(); const { push3D } = undoRedo3DStore(); - const { removeAsset } = assetStore(); const { zoneAssetId, setZoneAssetId } = useZoneAssetId(); const { resourceManagementId, setResourceManagementId } = useResourceManagementId(); const { removeEvent, getEventByModelUuid } = eventStore(); const { getIsEventInProduct, addPoint, deleteEvent, selectedProduct } = productStore(); const { setSelectedAsset, clearSelectedAsset } = useSelectedAsset(); const { deletableFloorAsset, setDeletableFloorAsset, selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore(); + const { removeAssetFromScene } = useAssetResponseHandler(); const { selectedVersion } = versionStore(); const { projectId } = useParams(); const { userId, organization } = getUserData(); @@ -130,6 +131,18 @@ export function useModelEventHandlers({ boundingBox, groupRef, asset }: { boundi modelName: asset.modelName, versionId: selectedVersion?.versionId || "", projectId: projectId || "", + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error removing asset`); + return; + } + if (data.message === "Model deleted successfully") { + removeAssetFromScene(data.data.modelUuid, () => { + echo.log(`Removed asset: ${data.data.modelName}`); + }); + } else { + echo.error(`Error removing asset: ${data?.data?.modelName}`); + } }); } else { // SOCKET @@ -154,8 +167,6 @@ export function useModelEventHandlers({ boundingBox, groupRef, asset }: { boundi updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event); }); - removeAsset(asset.modelUuid); - push3D({ type: "Scene", actions: [ diff --git a/app/src/modules/builder/asset/responseHandler/useAssetResponseHandler.ts b/app/src/modules/builder/asset/responseHandler/useAssetResponseHandler.ts index 2926e1e..82eefa3 100644 --- a/app/src/modules/builder/asset/responseHandler/useAssetResponseHandler.ts +++ b/app/src/modules/builder/asset/responseHandler/useAssetResponseHandler.ts @@ -1,20 +1,30 @@ import { useCallback } from "react"; +import { useSceneContext } from "../../../scene/sceneContext"; function useAssetResponseHandler() { + const { assetStore } = useSceneContext(); + const { addAsset, updateAsset, removeAsset } = assetStore(); + const addAssetToScene = useCallback((asset: Asset, callback?: () => void) => { - console.log("Adding asset:", asset); + addAsset(asset); if (callback) callback(); }, []); - const removeAssetFromScene = useCallback((assetId: string, callback?: () => void) => { - console.log("Removing asset with id:", assetId); + const updateAssetInScene = useCallback((asset: Asset, callback?: () => void) => { + updateAsset(asset.modelUuid, asset); if (callback) callback(); }, []); - const duplicateAssetInScene = useCallback((assetId: string, callback?: () => void) => { - console.log("Duplicating asset with id:", assetId); + const removeAssetFromScene = useCallback((modelUuid: string, callback?: () => void) => { + removeAsset(modelUuid); + + if (callback) callback(); + }, []); + + const duplicateAssetInScene = useCallback((modelUuid: string, callback?: () => void) => { + console.log("Duplicating asset with id:", modelUuid); if (callback) callback(); }, []); @@ -27,6 +37,7 @@ function useAssetResponseHandler() { return { addAssetToScene, + updateAssetInScene, removeAssetFromScene, duplicateAssetInScene, pasteAssetToScene, diff --git a/app/src/modules/collaboration/socket/builderResponses.tsx b/app/src/modules/collaboration/socket/builderResponses.tsx index 29f4782..28c9ee9 100644 --- a/app/src/modules/collaboration/socket/builderResponses.tsx +++ b/app/src/modules/collaboration/socket/builderResponses.tsx @@ -4,28 +4,134 @@ import useAssetResponseHandler from "../../builder/asset/responseHandler/useAsse function BuilderResponses() { const { builderSocket } = useSocketStore(); - const { addAssetToScene, removeAssetFromScene } = useAssetResponseHandler(); + const { addAssetToScene, updateAssetInScene, removeAssetFromScene } = useAssetResponseHandler(); //#region Asset useEffect(() => { if (!builderSocket) return; builderSocket.on("v1:model-asset:response:add", (data: any) => { - if (!data.message) return; - if (data.message === "Model created successfully") { - } else if (data.message === "Updated successfully") { + if (!data.message || !data.data) { + echo.error(`Error adding or updating asset`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + addAssetToScene(model, () => { + echo.log(`Added asset: ${model.modelName}`); + }); + } else if (data.message === "Model updated successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + updateAssetInScene(model, () => { + echo.log(`Updated asset: ${model.modelName}`); + }); + } else { + removeAssetFromScene(data.data.modelUuid, () => { + echo.error(`Error adding asset: ${data?.data?.modelName}`); + }); + } + }); + + builderSocket.on("v1:model-asset:response:copy", (data: any) => { + if (!data.message || !data.data) { + echo.error(`Error copying asset`); + return; + } + if (data.message === "Model copied successfully") { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + updateAssetInScene(model, () => { + echo.log(`Copied asset: ${model.modelName}`); + }); + } else { + if (!data.data.modelUuid) return; + removeAssetFromScene(data.data.modelUuid, () => { + echo.error(`Error copying asset: ${data?.data?.modelName}`); + }); + } + }); + + builderSocket.on("v1:model-asset:response:duplicate", (data: any) => { + if (!data.message || !data.data) { + echo.error(`Error duplicating asset`); + return; + } + if (data.message === "Model duplicated successfully") { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + updateAssetInScene(model, () => { + echo.log(`Duplicated asset: ${model.modelName}`); + }); + } else { + echo.error(`Error duplicating asset: ${data?.data?.modelName}`); } }); builderSocket.on("v1:model-asset:response:delete", (data: any) => { - if (!data.message) return; + if (!data.message || !data.data) { + echo.error(`Error removing asset`); + return; + } if (data.message === "Model deleted successfully") { + removeAssetFromScene(data.data.modelUuid, () => { + echo.log(`Removed asset: ${data.data.modelName}`); + }); + } else { + echo.error(`Error removing asset: ${data?.data?.modelName}`); } }); return () => { if (builderSocket) { builderSocket.off("v1:model-asset:response:add"); + builderSocket.off("v1:model-asset:response:copy"); + builderSocket.off("v1:model-asset:response:duplicate"); builderSocket.off("v1:model-asset:response:delete"); } }; diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx index fd39ae6..5e0c52e 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx @@ -1,14 +1,15 @@ import * as THREE from "three"; import * as Types from "../../../../../types/world/worldTypes"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { useFrame, useThree } from "@react-three/fiber"; -import { SkeletonUtils } from "three-stdlib"; -import { useContextActionStore, useToggleView } from "../../../../../store/builder/store"; -import { useSocketStore } from "../../../../../store/socket/useSocketStore"; -import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys"; import { useParams } from "react-router-dom"; -import { getUserData } from "../../../../../functions/getUserData"; +import { SkeletonUtils } from "three-stdlib"; +import { useFrame, useThree } from "@react-three/fiber"; import { useSceneContext } from "../../../sceneContext"; +import { useSocketStore } from "../../../../../store/socket/useSocketStore"; +import { useContextActionStore, useToggleView } from "../../../../../store/builder/store"; +import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys"; +import { getUserData } from "../../../../../functions/getUserData"; +import useAssetResponseHandler from "../../../../builder/asset/responseHandler/useAssetResponseHandler"; import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi"; @@ -24,7 +25,6 @@ const CopyPasteControls3D = () => { const { assets, addAsset, - updateAsset, removeAsset, getAssetById, selectedAssets, @@ -39,6 +39,7 @@ const CopyPasteControls3D = () => { rotatedObjects, setRotatedObjects, } = assetStore(); + const { updateAssetInScene } = useAssetResponseHandler(); const { selectedVersion } = versionStore(); const { userId, organization } = getUserData(); @@ -515,27 +516,42 @@ const CopyPasteControls3D = () => { eventData: eventData, versionId: selectedVersion?.versionId || "", projectId: projectId, - }); + }) + .then((data) => { + if (!data.message || !data.data) { + echo.error(`Error pasting asset: ${newFloorItem.modelUuid}`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + eventData: data.data.eventData, + }; + + updateAssetInScene(model, () => { + echo.log(`Pasted asset: ${model.modelName}`); + }); + } else { + echo.error(`Error pasting asset: ${newFloorItem.modelUuid}`); + } + }) + .catch(() => { + echo.error(`Error pasting asset: ${newFloorItem.modelUuid}`); + clearSelection(); + }); } else { // SOCKET - builderSocket.emit("v1:model-asset:add", data); + builderSocket.emit("v1:model-asset:copy", data); } - - const asset: Asset = { - modelUuid: data.modelUuid, - modelName: data.modelName, - assetId: data.assetId, - position: [position.x, 0, position.z], - rotation: [data.rotation.x, data.rotation.y, data.rotation.z], - isLocked: data.isLocked, - isCollidable: false, - isVisible: data.isVisible, - opacity: 1, - eventData: data.eventData, - }; - - updateAsset(asset.modelUuid, asset); } else { const data = { organization, @@ -565,26 +581,41 @@ const CopyPasteControls3D = () => { isVisible: true, versionId: selectedVersion?.versionId || "", projectId: projectId, - }); + }) + .then((data) => { + if (!data.message || !data.data) { + echo.error(`Error pasting asset: ${newFloorItem.modelUuid}`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + }; + + updateAssetInScene(model, () => { + echo.log(`Pasted asset: ${model.modelUuid}`); + }); + } else { + echo.error(`Error pasting asset: ${newFloorItem.modelUuid}`); + } + }) + .catch(() => { + echo.error(`Error pasting asset: ${newFloorItem.modelUuid}`); + clearSelection(); + }); } else { // SOCKET - builderSocket.emit("v1:model-asset:add", data); + builderSocket.emit("v1:model-asset:copy", data); } - - const asset: Asset = { - modelUuid: data.modelUuid, - modelName: data.modelName, - assetId: data.assetId, - position: [position.x, 0, position.z], - rotation: [data.rotation.x, data.rotation.y, data.rotation.z], - isLocked: data.isLocked, - isCollidable: false, - isVisible: data.isVisible, - opacity: 1, - }; - - updateAsset(asset.modelUuid, asset); } assetsToCopy.push({ @@ -625,7 +656,6 @@ const CopyPasteControls3D = () => { actions: undoActions, }); - echo.success("Object added!"); clearSelection(); }; diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx index 6c28279..271566d 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx @@ -1,15 +1,16 @@ import * as THREE from "three"; import * as Types from "../../../../../types/world/worldTypes"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { useFrame, useThree } from "@react-three/fiber"; -import { SkeletonUtils } from "three-stdlib"; -import { useContextActionStore, useToggleView } from "../../../../../store/builder/store"; -import { useSocketStore } from "../../../../../store/socket/useSocketStore"; -import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys"; import { useParams } from "react-router-dom"; -import { getUserData } from "../../../../../functions/getUserData"; +import { SkeletonUtils } from "three-stdlib"; +import { useFrame, useThree } from "@react-three/fiber"; import { useSceneContext } from "../../../sceneContext"; +import { useSocketStore } from "../../../../../store/socket/useSocketStore"; +import { useContextActionStore, useToggleView } from "../../../../../store/builder/store"; +import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys"; +import { getUserData } from "../../../../../functions/getUserData"; import { handleAssetPositionSnap } from "./functions/handleAssetPositionSnap"; +import useAssetResponseHandler from "../../../../builder/asset/responseHandler/useAssetResponseHandler"; import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi"; @@ -25,7 +26,6 @@ const DuplicationControls3D = () => { const { assets, addAsset, - updateAsset, removeAsset, getAssetById, selectedAssets, @@ -38,6 +38,7 @@ const DuplicationControls3D = () => { rotatedObjects, setRotatedObjects, } = assetStore(); + const { updateAssetInScene } = useAssetResponseHandler(); const { selectedVersion } = versionStore(); const { userId, organization } = getUserData(); @@ -577,27 +578,42 @@ const DuplicationControls3D = () => { eventData: eventData, versionId: selectedVersion?.versionId || "", projectId: projectId, - }); + }) + .then((data) => { + if (!data.message || !data.data) { + echo.error(`Error duplicating asset: ${newFloorItem.modelUuid}`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + eventData: data.data.eventData, + }; + + updateAssetInScene(model, () => { + echo.log(`Duplicated asset: ${model.modelName}`); + }); + } else { + echo.error(`Error duplicating asset: ${newFloorItem.modelUuid}`); + } + }) + .catch(() => { + echo.error(`Error duplicating asset: ${newFloorItem.modelUuid}`); + clearSelection(); + }); } else { // SOCKET - builderSocket.emit("v1:model-asset:add", data); + builderSocket.emit("v1:model-asset:duplicate", data); } - - const asset: Asset = { - modelUuid: data.modelUuid, - modelName: data.modelName, - assetId: data.assetId, - position: [position.x, position.y, position.z], - rotation: [data.rotation.x, data.rotation.y, data.rotation.z], - isLocked: data.isLocked, - isCollidable: false, - isVisible: data.isVisible, - opacity: 1, - eventData: data.eventData, - }; - - updateAsset(asset.modelUuid, asset); } else { const data = { organization, @@ -627,25 +643,41 @@ const DuplicationControls3D = () => { isVisible: true, versionId: selectedVersion?.versionId || "", projectId: projectId, - }); + }) + .then((data) => { + if (!data.message || !data.data) { + echo.error(`Error duplicating asset: ${newFloorItem.modelUuid}`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + }; + + updateAssetInScene(model, () => { + echo.log(`Duplicated asset: ${model.modelUuid}`); + }); + } else { + echo.error(`Error duplicating asset: ${newFloorItem.modelUuid}`); + } + }) + .catch(() => { + echo.error(`Error duplicating asset: ${newFloorItem.modelUuid}`); + clearSelection(); + }); } else { // SOCKET - builderSocket.emit("v1:model-asset:add", data); + builderSocket.emit("v1:model-asset:duplicate", data); } - const asset: Asset = { - modelUuid: data.modelUuid, - modelName: data.modelName, - assetId: data.assetId, - position: [position.x, position.y, position.z], - rotation: [data.rotation.x, data.rotation.y, data.rotation.z], - isLocked: data.isLocked, - isCollidable: false, - isVisible: data.isVisible, - opacity: 1, - }; - - updateAsset(asset.modelUuid, asset); } assetsToDuplicate.push({ @@ -686,7 +718,6 @@ const DuplicationControls3D = () => { actions: undoActions, }); - echo.success("Object duplicated!"); clearSelection(); }; diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx index e7ea465..ced7fa9 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx @@ -1,18 +1,19 @@ import * as THREE from "three"; import * as Types from "../../../../../types/world/worldTypes"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { useFrame, useThree } from "@react-three/fiber"; -import { useContextActionStore, useToggleView, useToolMode } from "../../../../../store/builder/store"; -import { useSocketStore } from "../../../../../store/socket/useSocketStore"; -import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys"; -import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi"; -import { handleAssetPositionSnap } from "./functions/handleAssetPositionSnap"; -import DistanceFindingControls from "./distanceFindingControls"; import { useParams } from "react-router-dom"; -import { getUserData } from "../../../../../functions/getUserData"; +import { useFrame, useThree } from "@react-three/fiber"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useSceneContext } from "../../../sceneContext"; import useModuleStore from "../../../../../store/ui/useModuleStore"; +import { useSocketStore } from "../../../../../store/socket/useSocketStore"; +import { useContextActionStore, useToggleView, useToolMode } from "../../../../../store/builder/store"; +import { handleAssetPositionSnap } from "./functions/handleAssetPositionSnap"; +import DistanceFindingControls from "./distanceFindingControls"; +import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys"; +import { getUserData } from "../../../../../functions/getUserData"; +import useAssetResponseHandler from "../../../../builder/asset/responseHandler/useAssetResponseHandler"; +import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi"; import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi"; function MoveControls3D({ boundingBoxRef }: any) { @@ -41,6 +42,7 @@ function MoveControls3D({ boundingBoxRef }: any) { rotatedObjects, setRotatedObjects, } = assetStore(); + const { updateAssetInScene } = useAssetResponseHandler(); const { selectedVersion } = versionStore(); const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">(""); @@ -379,11 +381,6 @@ function MoveControls3D({ boundingBoxRef }: any) { } } - updateAsset(movedAsset.userData.modelUuid, { - position: [position.x, position.y, position.z], - rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z], - }); - const data = { organization, modelUuid: newFloorItem.modelUuid, @@ -412,7 +409,43 @@ function MoveControls3D({ boundingBoxRef }: any) { isVisible: true, versionId: selectedVersion?.versionId || "", projectId: projectId, - }); + }) + .then((data) => { + if (!data.message || !data.data) { + echo.error(`Error moving asset: ${newFloorItem.modelUuid}`); + resetToInitialPositions(); + clearSelection(); + return; + } + if (data.message === "Model updated successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + eventData: data.data.eventData, + }; + + updateAssetInScene(model, () => { + echo.log(`Moved asset: ${model.modelName}`); + clearSelection(); + }); + } else { + echo.error(`Error moving asset: ${newFloorItem.modelUuid}`); + resetToInitialPositions(); + clearSelection(); + } + }) + .catch(() => { + echo.error(`Error moving asset: ${newFloorItem.modelUuid}`); + resetToInitialPositions(); + clearSelection(); + }); } else { // SOCKET @@ -442,7 +475,6 @@ function MoveControls3D({ boundingBoxRef }: any) { }); } - echo.success("Object moved!"); setIsMoving(false); clearSelection(); setAxisConstraint(null); diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx index c05fa21..87a524e 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx @@ -11,6 +11,7 @@ import { useSceneContext } from "../../../sceneContext"; import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys"; import { handleAssetRotationSnap } from "./functions/handleAssetRotationSnap"; import useModuleStore from "../../../../../store/ui/useModuleStore"; +import useAssetResponseHandler from "../../../../builder/asset/responseHandler/useAssetResponseHandler"; import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi"; @@ -37,6 +38,7 @@ function RotateControls3D() { duplicatedObjects, setDuplicatedObjects, } = assetStore(); + const { updateAssetInScene } = useAssetResponseHandler(); const { selectedVersion } = versionStore(); const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">(""); @@ -335,11 +337,6 @@ function RotateControls3D() { } } - updateAsset(obj.userData.modelUuid, { - position: positionArray, - rotation: rotationArray, - }); - const data = { organization, modelUuid: newFloorItem.modelUuid, @@ -368,7 +365,43 @@ function RotateControls3D() { isVisible: true, versionId: selectedVersion?.versionId || "", projectId: projectId, - }); + }) + .then((data) => { + if (!data.message || !data.data) { + echo.error(`Error rotating asset: ${newFloorItem.modelUuid}`); + resetToInitialRotations(); + clearSelection(); + return; + } + if (data.message === "Model updated successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + eventData: data.data.eventData, + }; + + updateAssetInScene(model, () => { + echo.log(`Rotated asset: ${model.modelName}`); + clearSelection(); + }); + } else { + echo.error(`Error rotating asset: ${newFloorItem.modelUuid}`); + resetToInitialRotations(); + clearSelection(); + } + }) + .catch(() => { + echo.error(`Error rotating asset: ${newFloorItem.modelUuid}`); + resetToInitialRotations(); + clearSelection(); + }); } else { // SOCKET diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx index f675529..111170d 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx @@ -19,6 +19,7 @@ import TransformControls3D from "./transformControls3D"; import { useBuilderStore } from "../../../../../store/builder/useBuilderStore"; import { deleteFloorAssetApi } from "../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorAssetApi"; +import useAssetResponseHandler from "../../../../builder/asset/responseHandler/useAssetResponseHandler"; const SelectionControls3D: React.FC = () => { const { camera, controls, gl, scene, raycaster, pointer } = useThree(); @@ -31,19 +32,8 @@ const SelectionControls3D: React.FC = () => { const { assetStore, eventStore, productStore, undoRedo3DStore, versionStore } = useSceneContext(); const { selectedDecal, selectedWall, selectedAisle, selectedFloor, selectedFloorAsset, selectedWallAsset } = useBuilderStore(); const { push3D } = undoRedo3DStore(); - const { - removeAsset, - getAssetById, - selectedAssets, - setSelectedAssets, - movedObjects, - rotatedObjects, - copiedObjects, - pastedObjects, - duplicatedObjects, - setPastedObjects, - setDuplicatedObjects, - } = assetStore(); + const { getAssetById, selectedAssets, setSelectedAssets, movedObjects, rotatedObjects, copiedObjects, pastedObjects, duplicatedObjects, setPastedObjects, setDuplicatedObjects } = assetStore(); + const { removeAssetFromScene } = useAssetResponseHandler(); const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]); const { selectedVersion } = versionStore(); const { projectId } = useParams(); @@ -320,8 +310,6 @@ const SelectionControls3D: React.FC = () => { const undoActions: UndoRedo3DAction[] = []; const assetsToDelete: AssetData[] = []; - const selectedUUIDs = selectedAssets.map((mesh: THREE.Object3D) => mesh.uuid); - selectedAssets.forEach((selectedMesh: THREE.Object3D) => { const asset = getAssetById(selectedMesh.userData.modelUuid); if (!asset) return; @@ -334,6 +322,18 @@ const SelectionControls3D: React.FC = () => { modelName: selectedMesh.userData.modelName, versionId: selectedVersion?.versionId || "", projectId: projectId || "", + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error removing asset`); + return; + } + if (data.message === "Model deleted successfully") { + removeAssetFromScene(data.data.modelUuid, () => { + echo.log(`Removed asset: ${data.data.modelName}`); + }); + } else { + echo.error(`Error removing asset: ${data?.data?.modelName}`); + } }); } else { // SOCKET @@ -358,8 +358,6 @@ const SelectionControls3D: React.FC = () => { updateBackend(productStore.getState().selectedProduct.productName, productStore.getState().selectedProduct.productUuid, projectId || "", event); }); - removeAsset(selectedMesh.uuid); - echo.success("Model Removed!"); selectedMesh.traverse((child: THREE.Object3D) => { @@ -403,10 +401,6 @@ const SelectionControls3D: React.FC = () => { actions: undoActions, }); - selectedUUIDs.forEach((uuid: string) => { - removeAsset(uuid); - }); - echo.warn("Selected models removed!"); clearSelection(); } diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/transformControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/transformControls3D.tsx index c8d3b0e..43e37ab 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/transformControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/transformControls3D.tsx @@ -1,11 +1,12 @@ import * as THREE from "three"; -import { useRef, useEffect, useState, useCallback } from "react"; +import { useParams } from "react-router-dom"; import { useThree } from "@react-three/fiber"; import { TransformControls } from "@react-three/drei"; +import { useRef, useEffect, useState, useCallback } from "react"; import { useToolMode } from "../../../../../store/builder/store"; import { useSocketStore } from "../../../../../store/socket/useSocketStore"; import { useSceneContext } from "../../../sceneContext"; -import { useParams } from "react-router-dom"; +import useAssetResponseHandler from "../../../../builder/asset/responseHandler/useAssetResponseHandler"; import { getUserData } from "../../../../../functions/getUserData"; import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi"; @@ -21,7 +22,8 @@ function TransformControls3D() { const { builderSocket } = useSocketStore(); const { assetStore, eventStore, productStore, undoRedo3DStore, versionStore } = useSceneContext(); const { push3D, subscribeUndoRedo } = undoRedo3DStore(); - const { updateAsset, getAssetById, selectedAssets, setSelectedAssets } = assetStore(); + const { getAssetById, selectedAssets, setSelectedAssets } = assetStore(); + const { updateAssetInScene } = useAssetResponseHandler(); const { userId, organization } = getUserData(); const { selectedVersion } = versionStore(); const { projectId } = useParams(); @@ -84,11 +86,6 @@ function TransformControls3D() { const asset = getAssetById(obj.uuid); if (!asset) return; - updateAsset(asset.modelUuid, { - position: [obj.position.x, obj.position.y, obj.position.z], - rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], - }); - if (asset.eventData) { const eventData = eventStore.getState().getEventByModelUuid(asset.modelUuid); const productData = productStore.getState().getEventByModelUuid(productStore.getState().selectedProduct.productUuid, asset.modelUuid); @@ -125,7 +122,37 @@ function TransformControls3D() { isVisible: true, versionId: selectedVersion?.versionId || "", projectId: projectId, - }); + }) + .then((data) => { + if (!data.message || !data.data) { + echo.error(`Error moving asset: ${asset.modelUuid}`); + + return; + } + if (data.message === "Model updated successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + eventData: data.data.eventData, + }; + + updateAssetInScene(model, () => { + echo.log(`Moved asset: ${model.modelName}`); + }); + } else { + echo.error(`Error moving asset: ${asset.modelUuid}`); + } + }) + .catch(() => { + echo.error(`Error moving asset: ${asset.modelUuid}`); + }); } else { // SOCKET @@ -147,7 +174,7 @@ function TransformControls3D() { builderSocket.emit("v1:model-asset:add", data); } }); - }, [selectedAssets, setSelectedAssets, getAssetById, updateAsset, eventStore, productStore, updateBackend, projectId, organization, builderSocket, selectedVersion, userId, push3D]); + }, [selectedAssets, setSelectedAssets, getAssetById, eventStore, productStore, updateBackend, projectId, organization, builderSocket, selectedVersion, userId, push3D]); useEffect(() => { const temp = tempObjectRef.current; @@ -244,11 +271,6 @@ function TransformControls3D() { newData, timeStap: new Date().toISOString(), }); - - updateAsset(asset.modelUuid, { - position: [obj.position.x, obj.position.y, obj.position.z], - rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], - }); }); if (assetsToUpdate.length > 0) { diff --git a/app/src/modules/scene/controls/transformControls/transformControls.tsx b/app/src/modules/scene/controls/transformControls/transformControls.tsx index e3c65d9..d16b078 100644 --- a/app/src/modules/scene/controls/transformControls/transformControls.tsx +++ b/app/src/modules/scene/controls/transformControls/transformControls.tsx @@ -8,6 +8,7 @@ import { useSceneContext } from "../../sceneContext"; import { useObjectPosition, useObjectRotation, useActiveTool } from "../../../../store/builder/store"; import { useSocketStore } from "../../../../store/socket/useSocketStore"; import { useBuilderStore } from "../../../../store/builder/useBuilderStore"; +import useAssetResponseHandler from "../../../builder/asset/responseHandler/useAssetResponseHandler"; import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys"; import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi"; @@ -24,7 +25,8 @@ export default function TransformControl() { const { builderSocket } = useSocketStore(); const { assetStore, eventStore, productStore, undoRedo3DStore, versionStore } = useSceneContext(); const { push3D } = undoRedo3DStore(); - const { updateAsset, getAssetById } = assetStore(); + const { getAssetById } = assetStore(); + const { updateAssetInScene } = useAssetResponseHandler(); const { userId, organization } = getUserData(); const { selectedVersion } = versionStore(); const { projectId } = useParams(); @@ -85,11 +87,6 @@ export default function TransformControl() { } } - updateAsset(asset.modelUuid, { - position: [selectedFloorAsset.position.x, 0, selectedFloorAsset.position.z], - rotation: [selectedFloorAsset.rotation.x, selectedFloorAsset.rotation.y, selectedFloorAsset.rotation.z] as [number, number, number], - }); - if (!builderSocket?.connected) { // API @@ -103,7 +100,37 @@ export default function TransformControl() { isVisible: true, versionId: selectedVersion?.versionId || "", projectId: projectId, - }); + }) + .then((data) => { + if (!data.message || !data.data) { + echo.error(`Error moving asset: ${asset.modelUuid}`); + + return; + } + if (data.message === "Model updated successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + eventData: data.data.eventData, + }; + + updateAssetInScene(model, () => { + echo.log(`Moved asset: ${model.modelName}`); + }); + } else { + echo.error(`Error moving asset: ${asset.modelUuid}`); + } + }) + .catch(() => { + echo.error(`Error moving asset: ${asset.modelUuid}`); + }); } else { // SOCKET diff --git a/app/src/modules/scene/controls/undoRedoControls/handlers/use3DRedoHandler.ts b/app/src/modules/scene/controls/undoRedoControls/handlers/use3DRedoHandler.ts index 4afde6c..60b7eab 100644 --- a/app/src/modules/scene/controls/undoRedoControls/handlers/use3DRedoHandler.ts +++ b/app/src/modules/scene/controls/undoRedoControls/handlers/use3DRedoHandler.ts @@ -2,6 +2,7 @@ import { useParams } from "react-router-dom"; import { getUserData } from "../../../../../functions/getUserData"; import { useSceneContext } from "../../../sceneContext"; import { useSocketStore } from "../../../../../store/socket/useSocketStore"; +import useAssetResponseHandler from "../../../../builder/asset/responseHandler/useAssetResponseHandler"; import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi"; @@ -9,10 +10,10 @@ import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floor import { deleteFloorAssetApi } from "../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorAssetApi"; function use3DRedoHandler() { - const { undoRedo3DStore, assetStore, productStore, eventStore, versionStore } = useSceneContext(); + const { undoRedo3DStore, productStore, eventStore, versionStore } = useSceneContext(); const { deleteEvent, selectedProduct } = productStore(); const { addEvent, removeEvent } = eventStore(); - const { updateAsset, removeAsset, addAsset } = assetStore(); + const { addAssetToScene, removeAssetFromScene, updateAssetInScene } = useAssetResponseHandler(); const { redo3D, peekRedo3D } = undoRedo3DStore(); const { selectedVersion } = versionStore(); const { userId, organization } = getUserData(); @@ -133,7 +134,6 @@ function use3DRedoHandler() { }; const addAssetToBackend = (assetData: Asset) => { - addAsset(assetData); if (projectId) { const data = { organization, @@ -170,6 +170,33 @@ function use3DRedoHandler() { eventData: data.eventData, versionId: selectedVersion?.versionId || "", projectId: projectId, + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error adding asset`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + addAssetToScene(model, () => { + echo.log(`Added asset: ${model.modelName}`); + }); + } else { + removeAssetFromScene(data.data.modelUuid, () => { + echo.error(`Error adding asset: ${data?.data?.modelName}`); + }); + } }); } else { // SOCKET @@ -188,6 +215,18 @@ function use3DRedoHandler() { modelName: assetData.modelName, versionId: selectedVersion?.versionId || "", projectId: projectId || "", + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error removing asset`); + return; + } + if (data.message === "Model deleted successfully") { + removeAssetFromScene(data.data.modelUuid, () => { + echo.log(`Removed asset: ${data.data.modelName}`); + }); + } else { + echo.error(`Error removing asset: ${data?.data?.modelName}`); + } }); } else { // SOCKET @@ -211,12 +250,9 @@ function use3DRedoHandler() { updatedEvents.forEach((event) => { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event); }); - - removeAsset(assetData.modelUuid); }; const updateAssetToBackend = (modelUuid: string, updatedData: Asset) => { - updateAsset(modelUuid, updatedData); if (projectId) { const data = { organization, @@ -246,6 +282,33 @@ function use3DRedoHandler() { isVisible: true, versionId: selectedVersion?.versionId || "", projectId: projectId, + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error adding asset`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + addAssetToScene(model, () => { + echo.log(`Added asset: ${model.modelName}`); + }); + } else { + removeAssetFromScene(data.data.modelUuid, () => { + echo.error(`Error adding asset: ${data?.data?.modelName}`); + }); + } }); } else { // SOCKET @@ -256,7 +319,6 @@ function use3DRedoHandler() { }; const copyAssetToBackend = (assetData: Asset) => { - addAsset(assetData); if (projectId) { const data = { organization, @@ -293,6 +355,33 @@ function use3DRedoHandler() { eventData: data.eventData, versionId: selectedVersion?.versionId || "", projectId: projectId, + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error adding asset`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + addAssetToScene(model, () => { + echo.log(`Added asset: ${model.modelName}`); + }); + } else { + removeAssetFromScene(data.data.modelUuid, () => { + echo.error(`Error adding asset: ${data?.data?.modelName}`); + }); + } }); } else { // SOCKET @@ -303,7 +392,6 @@ function use3DRedoHandler() { }; const duplicateAssetToBackend = (assetData: Asset) => { - addAsset(assetData); if (projectId) { const data = { organization, @@ -340,6 +428,33 @@ function use3DRedoHandler() { eventData: data.eventData, versionId: selectedVersion?.versionId || "", projectId: projectId, + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error adding asset`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + addAssetToScene(model, () => { + echo.log(`Added asset: ${model.modelName}`); + }); + } else { + removeAssetFromScene(data.data.modelUuid, () => { + echo.error(`Error adding asset: ${data?.data?.modelName}`); + }); + } }); } else { //SOCKET diff --git a/app/src/modules/scene/controls/undoRedoControls/handlers/use3DUndoHandler.ts b/app/src/modules/scene/controls/undoRedoControls/handlers/use3DUndoHandler.ts index 1bd299f..fa6b213 100644 --- a/app/src/modules/scene/controls/undoRedoControls/handlers/use3DUndoHandler.ts +++ b/app/src/modules/scene/controls/undoRedoControls/handlers/use3DUndoHandler.ts @@ -2,6 +2,7 @@ import { useParams } from "react-router-dom"; import { getUserData } from "../../../../../functions/getUserData"; import { useSceneContext } from "../../../sceneContext"; import { useSocketStore } from "../../../../../store/socket/useSocketStore"; +import useAssetResponseHandler from "../../../../builder/asset/responseHandler/useAssetResponseHandler"; import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi"; @@ -9,10 +10,10 @@ import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floor import { deleteFloorAssetApi } from "../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorAssetApi"; function use3DUndoHandler() { - const { undoRedo3DStore, assetStore, productStore, eventStore, versionStore } = useSceneContext(); + const { undoRedo3DStore, productStore, eventStore, versionStore } = useSceneContext(); const { deleteEvent, selectedProduct } = productStore(); const { addEvent, removeEvent } = eventStore(); - const { updateAsset, removeAsset, addAsset } = assetStore(); + const { addAssetToScene, removeAssetFromScene, updateAssetInScene } = useAssetResponseHandler(); const { undo3D, peekUndo3D } = undoRedo3DStore(); const { selectedVersion } = versionStore(); const { userId, organization } = getUserData(); @@ -132,7 +133,6 @@ function use3DUndoHandler() { }; const addAssetToBackend = (assetData: Asset) => { - addAsset(assetData); if (projectId) { const data = { organization, @@ -169,6 +169,33 @@ function use3DUndoHandler() { eventData: data.eventData, versionId: selectedVersion?.versionId || "", projectId: projectId, + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error adding asset`); + return; + } + if (data.message === "Model created successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + addAssetToScene(model, () => { + echo.log(`Added asset: ${model.modelName}`); + }); + } else { + removeAssetFromScene(data.data.modelUuid, () => { + echo.error(`Error adding asset: ${data?.data?.modelName}`); + }); + } }); } else { // SOCKET @@ -187,6 +214,18 @@ function use3DUndoHandler() { modelName: assetData.modelName, versionId: selectedVersion?.versionId || "", projectId: projectId || "", + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error removing asset`); + return; + } + if (data.message === "Model deleted successfully") { + removeAssetFromScene(data.data.modelUuid, () => { + echo.log(`Removed asset: ${data.data.modelName}`); + }); + } else { + echo.error(`Error removing asset: ${data?.data?.modelName}`); + } }); } else { // SOCKET @@ -210,16 +249,13 @@ function use3DUndoHandler() { updatedEvents.forEach((event) => { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event); }); - - removeAsset(assetData.modelUuid); }; const updateAssetToBackend = (modelUuid: string, updatedData: Asset) => { - updateAsset(modelUuid, updatedData); if (projectId) { const data = { organization, - modelUuid: updatedData.modelUuid, + modelUuid: modelUuid, modelName: updatedData.modelName, assetId: updatedData.assetId, position: updatedData.position, @@ -236,7 +272,7 @@ function use3DUndoHandler() { // REST setAssetsApi({ - modelUuid: updatedData.modelUuid, + modelUuid: modelUuid, modelName: updatedData.modelName, assetId: updatedData.assetId, position: updatedData.position, @@ -245,6 +281,33 @@ function use3DUndoHandler() { isVisible: true, versionId: selectedVersion?.versionId || "", projectId: projectId, + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error updating asset`); + return; + } + if (data.message === "Model updated successfully" && data.data) { + const model: Asset = { + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, + assetId: data.data.assetId, + position: data.data.position, + rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z], + isLocked: data.data.isLocked, + isCollidable: true, + isVisible: data.data.isVisible, + opacity: 1, + ...(data.data.eventData ? { eventData: data.data.eventData } : {}), + }; + + updateAssetInScene(model, () => { + echo.log(`Updated asset: ${model.modelName}`); + }); + } else { + removeAssetFromScene(data.data.modelUuid, () => { + echo.error(`Error updating asset: ${data?.data?.modelName}`); + }); + } }); } else { // SOCKET @@ -263,6 +326,18 @@ function use3DUndoHandler() { modelName: assetData.modelName, versionId: selectedVersion?.versionId || "", projectId: projectId || "", + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error removing asset`); + return; + } + if (data.message === "Model deleted successfully") { + removeAssetFromScene(data.data.modelUuid, () => { + echo.log(`Removed asset: ${data.data.modelName}`); + }); + } else { + echo.error(`Error removing asset: ${data?.data?.modelName}`); + } }); } else { // SOCKET @@ -286,8 +361,6 @@ function use3DUndoHandler() { updatedEvents.forEach((event) => { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event); }); - - removeAsset(assetData.modelUuid); }; const duplicateAssetToBackend = (assetData: Asset) => { @@ -299,6 +372,18 @@ function use3DUndoHandler() { modelName: assetData.modelName, versionId: selectedVersion?.versionId || "", projectId: projectId || "", + }).then((data) => { + if (!data.message || !data.data) { + echo.error(`Error removing asset`); + return; + } + if (data.message === "Model deleted successfully") { + removeAssetFromScene(data.data.modelUuid, () => { + echo.log(`Removed asset: ${data.data.modelName}`); + }); + } else { + echo.error(`Error removing asset: ${data?.data?.modelName}`); + } }); } else { // SOCKET @@ -322,8 +407,6 @@ function use3DUndoHandler() { updatedEvents.forEach((event) => { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event); }); - - removeAsset(assetData.modelUuid); }; const addWallAssetToBackend = (assetData: WallAsset) => {};