Merge branch 'main-dev' into dev-contextMenu
This commit is contained in:
@@ -17,6 +17,7 @@ import { getUserData } from "../../../functions/getUserData";
|
||||
import ContextControls from "./contextControls/contextControls";
|
||||
import SelectionControls2D from "./selectionControls/selection2D/selectionControls2D";
|
||||
import UndoRedo2DControls from "./undoRedoControls/undoRedo2D/undoRedo2DControls";
|
||||
import UndoRedo3DControls from "./undoRedoControls/undoRedo3D/undoRedo3DControls";
|
||||
|
||||
export default function Controls() {
|
||||
const controlsRef = useRef<CameraControls>(null);
|
||||
@@ -145,6 +146,8 @@ export default function Controls() {
|
||||
|
||||
<UndoRedo2DControls />
|
||||
|
||||
<UndoRedo3DControls />
|
||||
|
||||
<TransformControl />
|
||||
|
||||
<ContextControls />
|
||||
|
||||
@@ -28,7 +28,8 @@ const CopyPasteControls3D = ({
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||
const { socket } = useSocketStore();
|
||||
const { assetStore, eventStore } = useSceneContext();
|
||||
const { assetStore, eventStore, undoRedo3DStore } = useSceneContext();
|
||||
const { push3D } = undoRedo3DStore();
|
||||
const { addEvent } = eventStore();
|
||||
const { projectId } = useParams();
|
||||
const { assets, addAsset, updateAsset, removeAsset, getAssetById } = assetStore();
|
||||
@@ -209,6 +210,9 @@ const CopyPasteControls3D = ({
|
||||
const addPastedObjects = () => {
|
||||
if (pastedObjects.length === 0) return;
|
||||
|
||||
const undoActions: UndoRedo3DAction[] = [];
|
||||
const assetsToCopy: AssetData[] = [];
|
||||
|
||||
pastedObjects.forEach(async (pastedAsset: THREE.Object3D) => {
|
||||
if (pastedAsset) {
|
||||
const assetUuid = pastedAsset.userData.modelUuid;
|
||||
@@ -540,9 +544,45 @@ const CopyPasteControls3D = ({
|
||||
|
||||
updateAsset(asset.modelUuid, asset);
|
||||
}
|
||||
|
||||
assetsToCopy.push({
|
||||
type: "Asset",
|
||||
assetData: {
|
||||
modelUuid: newFloorItem.modelUuid,
|
||||
modelName: newFloorItem.modelName,
|
||||
assetId: newFloorItem.assetId,
|
||||
position: [position.x, position.y, position.z],
|
||||
rotation: [pastedAsset.rotation.x, pastedAsset.rotation.y, pastedAsset.rotation.z],
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
isCollidable: false,
|
||||
opacity: 1,
|
||||
eventData: newFloorItem.eventData || undefined
|
||||
},
|
||||
timeStap: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (assetsToCopy.length === 1) {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Asset-Copied",
|
||||
asset: assetsToCopy[0]
|
||||
});
|
||||
} else {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Assets-Copied",
|
||||
assets: assetsToCopy
|
||||
});
|
||||
}
|
||||
|
||||
push3D({
|
||||
type: 'Scene',
|
||||
actions: undoActions
|
||||
});
|
||||
|
||||
echo.success("Object added!");
|
||||
clearSelection();
|
||||
};
|
||||
|
||||
@@ -26,7 +26,8 @@ const DuplicationControls3D = ({
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||
const { socket } = useSocketStore();
|
||||
const { assetStore, eventStore } = useSceneContext();
|
||||
const { assetStore, eventStore, undoRedo3DStore } = useSceneContext();
|
||||
const { push3D } = undoRedo3DStore();
|
||||
const { addEvent } = eventStore();
|
||||
const { projectId } = useParams();
|
||||
const { assets, addAsset, updateAsset, removeAsset, getAssetById } = assetStore();
|
||||
@@ -207,6 +208,9 @@ const DuplicationControls3D = ({
|
||||
const addDuplicatedAssets = () => {
|
||||
if (duplicatedObjects.length === 0) return;
|
||||
|
||||
const undoActions: UndoRedo3DAction[] = [];
|
||||
const assetsToDuplicate: AssetData[] = [];
|
||||
|
||||
duplicatedObjects.forEach(async (duplicatedAsset: THREE.Object3D) => {
|
||||
if (duplicatedAsset) {
|
||||
const assetUuid = duplicatedAsset.userData.modelUuid;
|
||||
@@ -538,9 +542,45 @@ const DuplicationControls3D = ({
|
||||
|
||||
updateAsset(asset.modelUuid, asset);
|
||||
}
|
||||
|
||||
assetsToDuplicate.push({
|
||||
type: "Asset",
|
||||
assetData: {
|
||||
modelUuid: newFloorItem.modelUuid,
|
||||
modelName: newFloorItem.modelName,
|
||||
assetId: newFloorItem.assetId,
|
||||
position: [position.x, position.y, position.z],
|
||||
rotation: [duplicatedAsset.rotation.x, duplicatedAsset.rotation.y, duplicatedAsset.rotation.z],
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
isCollidable: false,
|
||||
opacity: 1,
|
||||
eventData: newFloorItem.eventData || undefined
|
||||
},
|
||||
timeStap: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (assetsToDuplicate.length === 1) {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Asset-Copied",
|
||||
asset: assetsToDuplicate[0]
|
||||
});
|
||||
} else {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Assets-Copied",
|
||||
assets: assetsToDuplicate
|
||||
});
|
||||
}
|
||||
|
||||
push3D({
|
||||
type: 'Scene',
|
||||
actions: undoActions
|
||||
});
|
||||
|
||||
echo.success("Object duplicated!");
|
||||
clearSelection();
|
||||
};
|
||||
|
||||
@@ -37,7 +37,8 @@ function MoveControls3D({
|
||||
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("");
|
||||
const { userId, organization } = getUserData();
|
||||
const { projectId } = useParams();
|
||||
const { assetStore, eventStore, productStore } = useSceneContext();
|
||||
const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext();
|
||||
const { push3D } = undoRedo3DStore();
|
||||
const { updateAsset, getAssetById } = assetStore();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
@@ -292,6 +293,9 @@ function MoveControls3D({
|
||||
const placeMovedAssets = () => {
|
||||
if (movedObjects.length === 0) return;
|
||||
|
||||
const undoActions: UndoRedo3DAction[] = [];
|
||||
const assetsToUpdate: AssetData[] = [];
|
||||
|
||||
movedObjects.forEach(async (movedAsset: THREE.Object3D) => {
|
||||
if (movedAsset) {
|
||||
const assetUuid = movedAsset.userData.modelUuid;
|
||||
@@ -299,6 +303,32 @@ function MoveControls3D({
|
||||
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];
|
||||
|
||||
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
|
||||
]
|
||||
},
|
||||
newData: {
|
||||
...asset,
|
||||
position: [position.x, position.y, position.z],
|
||||
rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z]
|
||||
},
|
||||
timeStap: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
|
||||
const newFloorItem: Types.FloorItemType = {
|
||||
modelUuid: movedAsset.userData.modelUuid,
|
||||
@@ -376,6 +406,27 @@ function MoveControls3D({
|
||||
}
|
||||
});
|
||||
|
||||
if (assetsToUpdate.length > 0) {
|
||||
if (assetsToUpdate.length === 1) {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Asset-Update",
|
||||
asset: assetsToUpdate[0]
|
||||
});
|
||||
} else {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Assets-Update",
|
||||
assets: assetsToUpdate
|
||||
});
|
||||
}
|
||||
|
||||
push3D({
|
||||
type: 'Scene',
|
||||
actions: undoActions
|
||||
});
|
||||
}
|
||||
|
||||
echo.success("Object moved!");
|
||||
setIsMoving(false);
|
||||
clearSelection();
|
||||
|
||||
@@ -32,7 +32,8 @@ function RotateControls3D({
|
||||
const { socket } = useSocketStore();
|
||||
const { userId, organization } = getUserData();
|
||||
const { projectId } = useParams();
|
||||
const { assetStore, eventStore, productStore } = useSceneContext();
|
||||
const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext();
|
||||
const { push3D } = undoRedo3DStore();
|
||||
const { updateAsset } = assetStore();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
@@ -227,12 +228,43 @@ function RotateControls3D({
|
||||
const placeRotatedAssets = useCallback(() => {
|
||||
if (rotatedObjects.length === 0) return;
|
||||
|
||||
const undoActions: UndoRedo3DAction[] = [];
|
||||
const assetsToUpdate: AssetData[] = [];
|
||||
|
||||
rotatedObjects.forEach((obj: THREE.Object3D) => {
|
||||
if (obj && obj.userData.modelUuid) {
|
||||
const asset = assetStore.getState().getAssetById(obj.userData.modelUuid);
|
||||
if (!asset) return;
|
||||
|
||||
const rotationArray: [number, number, number] = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||
|
||||
const positionArray: [number, number, number] = [obj.position.x, obj.position.y, obj.position.z];
|
||||
|
||||
if (initialRotations[obj.uuid] && initialPositions[obj.uuid]) {
|
||||
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
|
||||
]
|
||||
},
|
||||
newData: {
|
||||
...asset,
|
||||
position: positionArray,
|
||||
rotation: rotationArray
|
||||
},
|
||||
timeStap: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
|
||||
const newFloorItem: Types.FloorItemType = {
|
||||
modelUuid: obj.userData.modelUuid,
|
||||
modelName: obj.userData.modelName,
|
||||
@@ -310,6 +342,27 @@ function RotateControls3D({
|
||||
}
|
||||
});
|
||||
|
||||
if (assetsToUpdate.length > 0) {
|
||||
if (assetsToUpdate.length === 1) {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Asset-Update",
|
||||
asset: assetsToUpdate[0]
|
||||
});
|
||||
} else {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Assets-Update",
|
||||
assets: assetsToUpdate
|
||||
});
|
||||
}
|
||||
|
||||
push3D({
|
||||
type: 'Scene',
|
||||
actions: undoActions
|
||||
});
|
||||
}
|
||||
|
||||
setIsRotating(false);
|
||||
clearSelection();
|
||||
}, [rotatedObjects, eventStore, productStore, selectedProduct, updateBackend, projectId, updateAsset, organization, socket, selectedVersion, userId]);
|
||||
|
||||
@@ -31,9 +31,10 @@ const SelectionControls3D: React.FC = () => {
|
||||
const boundingBoxRef = useRef<THREE.Mesh>();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { socket } = useSocketStore();
|
||||
const { assetStore, eventStore, productStore } = useSceneContext();
|
||||
const { removeAsset } = assetStore();
|
||||
const { contextAction, setContextAction } = useContextActionStore()
|
||||
const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext();
|
||||
const { push3D } = undoRedo3DStore();
|
||||
const { removeAsset, getAssetById } = assetStore();
|
||||
const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
|
||||
const { toolMode } = useToolMode();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
@@ -274,12 +275,18 @@ const SelectionControls3D: React.FC = () => {
|
||||
const deleteSelection = () => {
|
||||
if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
|
||||
|
||||
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;
|
||||
|
||||
//REST
|
||||
|
||||
// const response = await deleteFloorItem(organization, selectedMesh.userData.modelUuid, selectedMesh.userData.modelName);
|
||||
// const response = deleteFloorItem(organization, selectedMesh.userData.modelUuid, selectedMesh.userData.modelName);
|
||||
|
||||
//SOCKET
|
||||
|
||||
@@ -329,6 +336,31 @@ const SelectionControls3D: React.FC = () => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
assetsToDelete.push({
|
||||
type: "Asset",
|
||||
assetData: asset,
|
||||
timeStap: new Date().toISOString()
|
||||
});
|
||||
});
|
||||
|
||||
if (assetsToDelete.length === 1) {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Asset-Delete",
|
||||
asset: assetsToDelete[0]
|
||||
});
|
||||
} else {
|
||||
undoActions.push({
|
||||
module: "builder",
|
||||
actionType: "Assets-Delete",
|
||||
assets: assetsToDelete
|
||||
});
|
||||
}
|
||||
|
||||
push3D({
|
||||
type: 'Scene',
|
||||
actions: undoActions
|
||||
});
|
||||
|
||||
selectedUUIDs.forEach((uuid: string) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as THREE from "three";
|
||||
import { useSelectedFloorItem, useObjectPosition, useObjectRotation, useActiveTool, useSocketStore } from "../../../../store/builder/store";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
|
||||
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||
// import { setAssetsApi } from "../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
|
||||
@@ -15,6 +15,7 @@ import { useVersionContext } from "../../../builder/version/versionContext";
|
||||
|
||||
export default function TransformControl() {
|
||||
const state = useThree();
|
||||
const ref = useRef(null);
|
||||
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
||||
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
|
||||
const { setObjectPosition } = useObjectPosition();
|
||||
@@ -23,7 +24,8 @@ export default function TransformControl() {
|
||||
const { socket } = useSocketStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { assetStore, eventStore, productStore } = useSceneContext();
|
||||
const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext();
|
||||
const { push3D } = undoRedo3DStore();
|
||||
const { updateAsset, getAssetById } = assetStore();
|
||||
const { userId, organization } = getUserData();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
@@ -136,13 +138,37 @@ export default function TransformControl() {
|
||||
projectId
|
||||
};
|
||||
|
||||
// console.log('data: ', data);
|
||||
socket.emit("v1:model-asset:add", data);
|
||||
|
||||
push3D({
|
||||
type: 'Scene',
|
||||
actions: [
|
||||
{
|
||||
module: "builder",
|
||||
actionType: "Asset-Update",
|
||||
asset: {
|
||||
type: "Asset",
|
||||
assetData: asset,
|
||||
newData: {
|
||||
...asset,
|
||||
position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z],
|
||||
rotation: [selectedFloorItem.rotation.x, selectedFloorItem.rotation.y, selectedFloorItem.rotation.z],
|
||||
},
|
||||
timeStap: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
const isTextInput = (element: Element | null): boolean =>
|
||||
element instanceof HTMLInputElement ||
|
||||
element instanceof HTMLTextAreaElement ||
|
||||
element?.getAttribute("contenteditable") === "true";
|
||||
if (isTextInput(document.activeElement)) return;
|
||||
const keyCombination = detectModifierKeys(e);
|
||||
if (!selectedFloorItem) return;
|
||||
if (keyCombination === "G") {
|
||||
@@ -186,8 +212,9 @@ export default function TransformControl() {
|
||||
<>
|
||||
{(selectedFloorItem && transformMode) &&
|
||||
<TransformControls
|
||||
ref={ref}
|
||||
showX={transformMode === "translate"}
|
||||
showY={transformMode === "rotate"}
|
||||
showY={transformMode === "rotate" || transformMode === "translate"}
|
||||
showZ={transformMode === "translate"}
|
||||
object={selectedFloorItem}
|
||||
mode={transformMode}
|
||||
|
||||
@@ -16,7 +16,7 @@ import { useSocketStore } from "../../../../../store/builder/store";
|
||||
// import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
|
||||
// import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
|
||||
|
||||
function useRedoHandler() {
|
||||
function use2DRedoHandler() {
|
||||
const { undoRedo2DStore, wallStore, floorStore, zoneStore, aisleStore } = useSceneContext();
|
||||
const { redo2D, peekRedo2D } = undoRedo2DStore();
|
||||
const { addWall, removeWall, updateWall } = wallStore();
|
||||
@@ -352,4 +352,4 @@ function useRedoHandler() {
|
||||
return { handleRedo };
|
||||
}
|
||||
|
||||
export default useRedoHandler;
|
||||
export default use2DRedoHandler;
|
||||
@@ -16,7 +16,7 @@ import { useSocketStore } from "../../../../../store/builder/store";
|
||||
// import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
|
||||
// import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
|
||||
|
||||
function useUndoHandler() {
|
||||
function use2DUndoHandler() {
|
||||
const { undoRedo2DStore, wallStore, floorStore, zoneStore, aisleStore } = useSceneContext();
|
||||
const { undo2D, peekUndo2D } = undoRedo2DStore();
|
||||
const { addWall, removeWall, updateWall } = wallStore();
|
||||
@@ -67,38 +67,37 @@ function useUndoHandler() {
|
||||
}
|
||||
|
||||
undo2D();
|
||||
|
||||
};
|
||||
|
||||
const handleCreate = (point: UndoRedo2DDataTypeSchema) => {
|
||||
switch (point.type) {
|
||||
case 'Wall': createWallFromBackend(point.lineData); break;
|
||||
case 'Floor': createFloorFromBackend(point.lineData); break;
|
||||
case 'Zone': createZoneFromBackend(point.lineData); break;
|
||||
case 'Aisle': createAisleFromBackend(point.lineData); break;
|
||||
case 'Wall': createWallToBackend(point.lineData); break;
|
||||
case 'Floor': createFloorToBackend(point.lineData); break;
|
||||
case 'Zone': createZoneToBackend(point.lineData); break;
|
||||
case 'Aisle': createAisleToBackend(point.lineData); break;
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemove = (point: UndoRedo2DDataTypeSchema) => {
|
||||
switch (point.type) {
|
||||
case 'Wall': removeWallFromBackend(point.lineData.wallUuid); break;
|
||||
case 'Floor': removeFloorFromBackend(point.lineData.floorUuid); break;
|
||||
case 'Zone': removeZoneFromBackend(point.lineData.zoneUuid); break;
|
||||
case 'Aisle': removeAisleFromBackend(point.lineData.aisleUuid); break;
|
||||
case 'Wall': removeWallToBackend(point.lineData.wallUuid); break;
|
||||
case 'Floor': removeFloorToBackend(point.lineData.floorUuid); break;
|
||||
case 'Zone': removeZoneToBackend(point.lineData.zoneUuid); break;
|
||||
case 'Aisle': removeAisleToBackend(point.lineData.aisleUuid); break;
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpdate = (point: UndoRedo2DDataTypeSchema) => {
|
||||
switch (point.type) {
|
||||
case 'Wall': updateWallFromBackend(point.lineData.wallUuid, point.lineData); break;
|
||||
case 'Floor': updateFloorFromBackend(point.lineData.floorUuid, point.lineData); break;
|
||||
case 'Zone': updateZoneFromBackend(point.lineData.zoneUuid, point.lineData); break;
|
||||
case 'Aisle': updateAisleFromBackend(point.lineData.aisleUuid, point.lineData); break;
|
||||
case 'Wall': updateWallToBackend(point.lineData.wallUuid, point.lineData); break;
|
||||
case 'Floor': updateFloorToBackend(point.lineData.floorUuid, point.lineData); break;
|
||||
case 'Zone': updateZoneToBackend(point.lineData.zoneUuid, point.lineData); break;
|
||||
case 'Aisle': updateAisleToBackend(point.lineData.aisleUuid, point.lineData); break;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const createWallFromBackend = (wallData: Wall) => {
|
||||
const createWallToBackend = (wallData: Wall) => {
|
||||
addWall(wallData);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -119,7 +118,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const removeWallFromBackend = (wallUuid: string) => {
|
||||
const removeWallToBackend = (wallUuid: string) => {
|
||||
removeWall(wallUuid);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -140,7 +139,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const updateWallFromBackend = (wallUuid: string, updatedData: Wall) => {
|
||||
const updateWallToBackend = (wallUuid: string, updatedData: Wall) => {
|
||||
updateWall(wallUuid, updatedData);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -161,7 +160,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const createFloorFromBackend = (floorData: Floor) => {
|
||||
const createFloorToBackend = (floorData: Floor) => {
|
||||
addFloor(floorData);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -182,7 +181,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const removeFloorFromBackend = (floorUuid: string) => {
|
||||
const removeFloorToBackend = (floorUuid: string) => {
|
||||
removeFloor(floorUuid);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -203,7 +202,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const updateFloorFromBackend = (floorUuid: string, updatedData: Floor) => {
|
||||
const updateFloorToBackend = (floorUuid: string, updatedData: Floor) => {
|
||||
updateFloor(floorUuid, updatedData);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -224,7 +223,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const createZoneFromBackend = (zoneData: Zone) => {
|
||||
const createZoneToBackend = (zoneData: Zone) => {
|
||||
addZone(zoneData);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -245,7 +244,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const removeZoneFromBackend = (zoneUuid: string) => {
|
||||
const removeZoneToBackend = (zoneUuid: string) => {
|
||||
removeZone(zoneUuid);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -266,7 +265,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const updateZoneFromBackend = (zoneUuid: string, updatedData: Zone) => {
|
||||
const updateZoneToBackend = (zoneUuid: string, updatedData: Zone) => {
|
||||
updateZone(zoneUuid, updatedData);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -287,7 +286,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const createAisleFromBackend = (aisleData: Aisle) => {
|
||||
const createAisleToBackend = (aisleData: Aisle) => {
|
||||
addAisle(aisleData);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -308,7 +307,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const removeAisleFromBackend = (aisleUuid: string) => {
|
||||
const removeAisleToBackend = (aisleUuid: string) => {
|
||||
removeAisle(aisleUuid);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -329,7 +328,7 @@ function useUndoHandler() {
|
||||
}
|
||||
};
|
||||
|
||||
const updateAisleFromBackend = (aisleUuid: string, updatedData: Aisle) => {
|
||||
const updateAisleToBackend = (aisleUuid: string, updatedData: Aisle) => {
|
||||
updateAisle(aisleUuid, updatedData);
|
||||
if (projectId) {
|
||||
// API
|
||||
@@ -353,4 +352,4 @@ function useUndoHandler() {
|
||||
return { handleUndo };
|
||||
}
|
||||
|
||||
export default useUndoHandler;
|
||||
export default use2DUndoHandler;
|
||||
@@ -0,0 +1,318 @@
|
||||
import { useParams } from "react-router-dom";
|
||||
import { getUserData } from "../../../../../functions/getUserData";
|
||||
import { useVersionContext } from "../../../../builder/version/versionContext";
|
||||
import { useSceneContext } from "../../../sceneContext";
|
||||
import { useProductContext } from "../../../../simulation/products/productContext";
|
||||
import { useSocketStore } from "../../../../../store/builder/store";
|
||||
|
||||
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||
|
||||
// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
|
||||
// import { deleteFloorItem } from "../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi";
|
||||
|
||||
function use3DRedoHandler() {
|
||||
const { undoRedo3DStore, assetStore, productStore, eventStore } = useSceneContext();
|
||||
const { deleteEvent } = productStore();
|
||||
const { addEvent, removeEvent } = eventStore();
|
||||
const { updateAsset, removeAsset, addAsset } = assetStore();
|
||||
const { redo3D, peekRedo3D } = undoRedo3DStore();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { userId, organization } = getUserData();
|
||||
const { projectId } = useParams();
|
||||
const { socket } = useSocketStore();
|
||||
|
||||
const updateBackend = (
|
||||
productName: string,
|
||||
productUuid: string,
|
||||
projectId: string,
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productUuid: productUuid,
|
||||
projectId: projectId,
|
||||
eventDatas: eventData,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
});
|
||||
};
|
||||
|
||||
const handleRedo = () => {
|
||||
const redoData = peekRedo3D();
|
||||
if (!redoData) return;
|
||||
|
||||
if (redoData.type === 'Scene') {
|
||||
const { actions } = redoData;
|
||||
|
||||
actions.forEach(action => {
|
||||
const { actionType } = action;
|
||||
|
||||
if ('asset' in action) {
|
||||
const asset = action.asset;
|
||||
|
||||
if (actionType === 'Asset-Add') {
|
||||
handleAdd(asset);
|
||||
} else if (actionType === 'Asset-Delete') {
|
||||
handleDelete(asset);
|
||||
} else if (actionType === 'Asset-Update') {
|
||||
handleUpdate(asset);
|
||||
} else if (actionType === 'Asset-Copied') {
|
||||
handleCopy(asset);
|
||||
} else if (actionType === 'Asset-Duplicated') {
|
||||
handleDuplicate(asset);
|
||||
}
|
||||
|
||||
} else if ('assets' in action) {
|
||||
const assets = action.assets;
|
||||
|
||||
if (actionType === 'Assets-Add') {
|
||||
assets.forEach(handleAdd);
|
||||
} else if (actionType === 'Assets-Delete') {
|
||||
assets.forEach(handleDelete);
|
||||
} else if (actionType === 'Assets-Update') {
|
||||
assets.forEach(handleUpdate);
|
||||
} else if (actionType === 'Assets-Copied') {
|
||||
assets.forEach(handleCopy);
|
||||
} else if (actionType === 'Assets-Duplicated') {
|
||||
assets.forEach(handleDuplicate);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (redoData.type === 'UI') {
|
||||
// Handle UI actions if needed
|
||||
}
|
||||
|
||||
redo3D();
|
||||
};
|
||||
|
||||
|
||||
const handleAdd = (asset: AssetData) => {
|
||||
switch (asset.type) {
|
||||
case 'Asset': addAssetToBackend(asset.assetData); break;
|
||||
case 'WallAsset': addWallAssetToBackend(asset.assetData); break;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = (asset: AssetData) => {
|
||||
switch (asset.type) {
|
||||
case 'Asset': deleteAssetToBackend(asset.assetData); break;
|
||||
case 'WallAsset': deleteWallAssetToBackend(asset.assetData); break;
|
||||
}
|
||||
}
|
||||
|
||||
const handleUpdate = (asset: AssetData) => {
|
||||
if (!asset.newData) return;
|
||||
switch (asset.type) {
|
||||
case 'Asset': updateAssetToBackend(asset.newData.modelUuid, asset.newData); break;
|
||||
case 'WallAsset': updateWallAssetToBackend(asset.newData.modelUuid, asset.newData); break;
|
||||
}
|
||||
}
|
||||
|
||||
const handleCopy = (asset: AssetData) => {
|
||||
switch (asset.type) {
|
||||
case 'Asset': copyAssetToBackend(asset.assetData); break;
|
||||
case 'WallAsset': copyWallAssetToBackend(asset.assetData); break;
|
||||
}
|
||||
}
|
||||
|
||||
const handleDuplicate = (asset: AssetData) => {
|
||||
switch (asset.type) {
|
||||
case 'Asset': duplicateAssetToBackend(asset.assetData); break;
|
||||
case 'WallAsset': duplicateWallAssetToBackend(asset.assetData); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const addAssetToBackend = (assetData: Asset) => {
|
||||
addAsset(assetData);
|
||||
if (projectId) {
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: assetData.modelUuid,
|
||||
modelName: assetData.modelName,
|
||||
assetId: assetData.assetId,
|
||||
position: assetData.position,
|
||||
rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: {},
|
||||
socketId: socket.id,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId,
|
||||
userId
|
||||
};
|
||||
|
||||
if (assetData.eventData) {
|
||||
data.eventData = assetData.eventData;
|
||||
addEvent(assetData.eventData as EventsSchema);
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
// setAssetsApi(data);
|
||||
|
||||
//SOCKET
|
||||
|
||||
socket.emit("v1:model-asset:add", data);
|
||||
}
|
||||
}
|
||||
|
||||
const deleteAssetToBackend = (assetData: Asset) => {
|
||||
//REST
|
||||
|
||||
// const response = deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: assetData.modelUuid,
|
||||
modelName: assetData.modelName,
|
||||
socketId: socket.id,
|
||||
userId,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId
|
||||
}
|
||||
|
||||
const response = socket.emit('v1:model-asset:delete', data)
|
||||
|
||||
removeEvent(assetData.modelUuid);
|
||||
const updatedEvents = deleteEvent(assetData.modelUuid);
|
||||
|
||||
updatedEvents.forEach((event) => {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productUuid,
|
||||
projectId || '',
|
||||
event
|
||||
);
|
||||
})
|
||||
|
||||
if (response) {
|
||||
|
||||
removeAsset(assetData.modelUuid);
|
||||
}
|
||||
}
|
||||
|
||||
const updateAssetToBackend = (modelUuid: string, updatedData: Asset) => {
|
||||
updateAsset(modelUuid, updatedData);
|
||||
if (projectId) {
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: updatedData.modelUuid,
|
||||
modelName: updatedData.modelName,
|
||||
assetId: updatedData.assetId,
|
||||
position: updatedData.position,
|
||||
rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId,
|
||||
userId
|
||||
};
|
||||
|
||||
// API
|
||||
|
||||
// setAssetsApi(data);
|
||||
|
||||
//SOCKET
|
||||
|
||||
socket.emit("v1:model-asset:add", data);
|
||||
}
|
||||
}
|
||||
|
||||
const copyAssetToBackend = (assetData: Asset) => {
|
||||
addAsset(assetData);
|
||||
if (projectId) {
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: assetData.modelUuid,
|
||||
modelName: assetData.modelName,
|
||||
assetId: assetData.assetId,
|
||||
position: assetData.position,
|
||||
rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: {},
|
||||
socketId: socket.id,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId,
|
||||
userId
|
||||
};
|
||||
|
||||
if (assetData.eventData) {
|
||||
data.eventData = assetData.eventData;
|
||||
addEvent(assetData.eventData as EventsSchema);
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
// setAssetsApi(data);
|
||||
|
||||
//SOCKET
|
||||
|
||||
socket.emit("v1:model-asset:add", data);
|
||||
}
|
||||
}
|
||||
|
||||
const duplicateAssetToBackend = (assetData: Asset) => {
|
||||
addAsset(assetData);
|
||||
if (projectId) {
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: assetData.modelUuid,
|
||||
modelName: assetData.modelName,
|
||||
assetId: assetData.assetId,
|
||||
position: assetData.position,
|
||||
rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: {},
|
||||
socketId: socket.id,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId,
|
||||
userId
|
||||
};
|
||||
|
||||
if (assetData.eventData) {
|
||||
data.eventData = assetData.eventData;
|
||||
addEvent(assetData.eventData as EventsSchema);
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
// setAssetsApi(data);
|
||||
|
||||
//SOCKET
|
||||
|
||||
socket.emit("v1:model-asset:add", data);
|
||||
}
|
||||
}
|
||||
|
||||
const addWallAssetToBackend = (assetData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
const deleteWallAssetToBackend = (assetData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
const updateWallAssetToBackend = (modelUuid: string, updatedData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
const copyWallAssetToBackend = (assetData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
const duplicateWallAssetToBackend = (assetData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
return { handleRedo };
|
||||
}
|
||||
|
||||
export default use3DRedoHandler;
|
||||
@@ -0,0 +1,323 @@
|
||||
import { useParams } from "react-router-dom";
|
||||
import { getUserData } from "../../../../../functions/getUserData";
|
||||
import { useVersionContext } from "../../../../builder/version/versionContext";
|
||||
import { useSceneContext } from "../../../sceneContext";
|
||||
import { useProductContext } from "../../../../simulation/products/productContext";
|
||||
import { useSocketStore } from "../../../../../store/builder/store";
|
||||
|
||||
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||
|
||||
// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
|
||||
// import { deleteFloorItem } from "../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi";
|
||||
|
||||
function use3DUndoHandler() {
|
||||
const { undoRedo3DStore, assetStore, productStore, eventStore } = useSceneContext();
|
||||
const { deleteEvent } = productStore();
|
||||
const { addEvent, removeEvent } = eventStore();
|
||||
const { updateAsset, removeAsset, addAsset } = assetStore();
|
||||
const { undo3D, peekUndo3D } = undoRedo3DStore();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { userId, organization } = getUserData();
|
||||
const { projectId } = useParams();
|
||||
const { socket } = useSocketStore();
|
||||
|
||||
const updateBackend = (
|
||||
productName: string,
|
||||
productUuid: string,
|
||||
projectId: string,
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productUuid: productUuid,
|
||||
projectId: projectId,
|
||||
eventDatas: eventData,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
});
|
||||
};
|
||||
|
||||
const handleUndo = () => {
|
||||
const unDoData = peekUndo3D();
|
||||
if (!unDoData) return;
|
||||
|
||||
if (unDoData.type === 'Scene') {
|
||||
const { actions } = unDoData;
|
||||
|
||||
actions.forEach(action => {
|
||||
const { actionType } = action;
|
||||
|
||||
if ('asset' in action) {
|
||||
const asset = action.asset;
|
||||
|
||||
if (actionType === 'Asset-Add') {
|
||||
handleDelete(asset);
|
||||
} else if (actionType === 'Asset-Delete') {
|
||||
handleAdd(asset);
|
||||
} else if (actionType === 'Asset-Update') {
|
||||
handleUpdate(asset);
|
||||
} else if (actionType === 'Asset-Copied') {
|
||||
handleCopy(asset);
|
||||
} else if (actionType === 'Asset-Duplicated') {
|
||||
handleDuplicate(asset);
|
||||
}
|
||||
|
||||
} else if ('assets' in action) {
|
||||
const assets = action.assets;
|
||||
|
||||
if (actionType === 'Assets-Add') {
|
||||
assets.forEach(handleDelete);
|
||||
} else if (actionType === 'Assets-Delete') {
|
||||
assets.forEach(handleAdd);
|
||||
} else if (actionType === 'Assets-Update') {
|
||||
assets.forEach(handleUpdate);
|
||||
} else if (actionType === 'Assets-Copied') {
|
||||
assets.forEach(handleCopy);
|
||||
} else if (actionType === 'Assets-Duplicated') {
|
||||
assets.forEach(handleDuplicate);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (unDoData.type === 'UI') {
|
||||
// Handle UI actions if needed
|
||||
}
|
||||
|
||||
undo3D();
|
||||
};
|
||||
|
||||
|
||||
const handleAdd = (asset: AssetData) => {
|
||||
switch (asset.type) {
|
||||
case 'Asset': addAssetToBackend(asset.assetData); break;
|
||||
case 'WallAsset': addWallAssetToBackend(asset.assetData); break;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = (asset: AssetData) => {
|
||||
switch (asset.type) {
|
||||
case 'Asset': deleteAssetToBackend(asset.assetData); break;
|
||||
case 'WallAsset': deleteWallAssetToBackend(asset.assetData); break;
|
||||
}
|
||||
}
|
||||
|
||||
const handleUpdate = (asset: AssetData) => {
|
||||
switch (asset.type) {
|
||||
case 'Asset': updateAssetToBackend(asset.assetData.modelUuid, asset.assetData); break;
|
||||
case 'WallAsset': updateWallAssetToBackend(asset.assetData.modelUuid, asset.assetData); break;
|
||||
}
|
||||
}
|
||||
|
||||
const handleCopy = (asset: AssetData) => {
|
||||
switch (asset.type) {
|
||||
case 'Asset': copyAssetToBackend(asset.assetData); break;
|
||||
case 'WallAsset': copyWallAssetToBackend(asset.assetData); break;
|
||||
}
|
||||
}
|
||||
|
||||
const handleDuplicate = (asset: AssetData) => {
|
||||
switch (asset.type) {
|
||||
case 'Asset': duplicateAssetToBackend(asset.assetData); break;
|
||||
case 'WallAsset': duplicateWallAssetToBackend(asset.assetData); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const addAssetToBackend = (assetData: Asset) => {
|
||||
addAsset(assetData);
|
||||
if (projectId) {
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: assetData.modelUuid,
|
||||
modelName: assetData.modelName,
|
||||
assetId: assetData.assetId,
|
||||
position: assetData.position,
|
||||
rotation: { x: assetData.rotation[0], y: assetData.rotation[1], z: assetData.rotation[2] },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: {},
|
||||
socketId: socket.id,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId,
|
||||
userId
|
||||
};
|
||||
|
||||
if (assetData.eventData) {
|
||||
data.eventData = assetData.eventData;
|
||||
addEvent(assetData.eventData as EventsSchema);
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
// setAssetsApi(data);
|
||||
|
||||
//SOCKET
|
||||
|
||||
socket.emit("v1:model-asset:add", data);
|
||||
}
|
||||
}
|
||||
|
||||
const deleteAssetToBackend = (assetData: Asset) => {
|
||||
//REST
|
||||
|
||||
// const response = deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: assetData.modelUuid,
|
||||
modelName: assetData.modelName,
|
||||
socketId: socket.id,
|
||||
userId,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId
|
||||
}
|
||||
|
||||
const response = socket.emit('v1:model-asset:delete', data)
|
||||
|
||||
removeEvent(assetData.modelUuid);
|
||||
const updatedEvents = deleteEvent(assetData.modelUuid);
|
||||
|
||||
updatedEvents.forEach((event) => {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productUuid,
|
||||
projectId || '',
|
||||
event
|
||||
);
|
||||
})
|
||||
|
||||
if (response) {
|
||||
|
||||
removeAsset(assetData.modelUuid);
|
||||
}
|
||||
}
|
||||
|
||||
const updateAssetToBackend = (modelUuid: string, updatedData: Asset) => {
|
||||
updateAsset(modelUuid, updatedData);
|
||||
if (projectId) {
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: updatedData.modelUuid,
|
||||
modelName: updatedData.modelName,
|
||||
assetId: updatedData.assetId,
|
||||
position: updatedData.position,
|
||||
rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId,
|
||||
userId
|
||||
};
|
||||
|
||||
// API
|
||||
|
||||
// setAssetsApi(data);
|
||||
|
||||
//SOCKET
|
||||
|
||||
socket.emit("v1:model-asset:add", data);
|
||||
}
|
||||
}
|
||||
|
||||
const copyAssetToBackend = (assetData: Asset) => {
|
||||
//REST
|
||||
|
||||
// const response = deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: assetData.modelUuid,
|
||||
modelName: assetData.modelName,
|
||||
socketId: socket.id,
|
||||
userId,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId
|
||||
}
|
||||
|
||||
const response = socket.emit('v1:model-asset:delete', data)
|
||||
|
||||
removeEvent(assetData.modelUuid);
|
||||
const updatedEvents = deleteEvent(assetData.modelUuid);
|
||||
|
||||
updatedEvents.forEach((event) => {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productUuid,
|
||||
projectId || '',
|
||||
event
|
||||
);
|
||||
})
|
||||
|
||||
if (response) {
|
||||
|
||||
removeAsset(assetData.modelUuid);
|
||||
}
|
||||
}
|
||||
|
||||
const duplicateAssetToBackend = (assetData: Asset) => {
|
||||
//REST
|
||||
|
||||
// const response = deleteFloorItem(organization, assetData.modelUuid, assetData.modelName);
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modelUuid: assetData.modelUuid,
|
||||
modelName: assetData.modelName,
|
||||
socketId: socket.id,
|
||||
userId,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
projectId
|
||||
}
|
||||
|
||||
const response = socket.emit('v1:model-asset:delete', data)
|
||||
|
||||
removeEvent(assetData.modelUuid);
|
||||
const updatedEvents = deleteEvent(assetData.modelUuid);
|
||||
|
||||
updatedEvents.forEach((event) => {
|
||||
updateBackend(
|
||||
selectedProduct.productName,
|
||||
selectedProduct.productUuid,
|
||||
projectId || '',
|
||||
event
|
||||
);
|
||||
})
|
||||
|
||||
if (response) {
|
||||
|
||||
removeAsset(assetData.modelUuid);
|
||||
}
|
||||
}
|
||||
|
||||
const addWallAssetToBackend = (assetData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
const deleteWallAssetToBackend = (assetData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
const updateWallAssetToBackend = (modelUuid: string, updatedData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
const copyWallAssetToBackend = (assetData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
const duplicateWallAssetToBackend = (assetData: WallAsset) => {
|
||||
|
||||
}
|
||||
|
||||
return { handleUndo };
|
||||
}
|
||||
|
||||
export default use3DUndoHandler;
|
||||
@@ -4,15 +4,15 @@ import { detectModifierKeys } from '../../../../../utils/shortcutkeys/detectModi
|
||||
import { useSocketStore, useToggleView } from '../../../../../store/builder/store';
|
||||
import { useVersionContext } from '../../../../builder/version/versionContext';
|
||||
|
||||
import useUndoHandler from '../handlers/useUndoHandler';
|
||||
import useRedoHandler from '../handlers/useRedoHandler';
|
||||
import use2DUndoHandler from '../handlers/use2DUndoHandler';
|
||||
import use2DRedoHandler from '../handlers/use2DRedoHandler';
|
||||
|
||||
function UndoRedo2DControls() {
|
||||
const { undoRedo2DStore } = useSceneContext();
|
||||
const { undoStack, redoStack } = undoRedo2DStore();
|
||||
const { toggleView } = useToggleView();
|
||||
const { handleUndo } = useUndoHandler();
|
||||
const { handleRedo } = useRedoHandler();
|
||||
const { handleUndo } = use2DUndoHandler();
|
||||
const { handleRedo } = use2DRedoHandler();
|
||||
const { socket } = useSocketStore();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useSceneContext } from '../../../sceneContext'
|
||||
import { detectModifierKeys } from '../../../../../utils/shortcutkeys/detectModifierKeys';
|
||||
import { useSocketStore, useToggleView } from '../../../../../store/builder/store';
|
||||
import { useVersionContext } from '../../../../builder/version/versionContext';
|
||||
import useModuleStore from '../../../../../store/useModuleStore';
|
||||
|
||||
import use3DUndoHandler from '../handlers/use3DUndoHandler';
|
||||
import use3DRedoHandler from '../handlers/use3DRedoHandler';
|
||||
|
||||
function UndoRedo3DControls() {
|
||||
const { undoRedo3DStore } = useSceneContext();
|
||||
const { undoStack, redoStack } = undoRedo3DStore();
|
||||
const { toggleView } = useToggleView();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { handleUndo } = use3DUndoHandler();
|
||||
const { handleRedo } = use3DRedoHandler();
|
||||
const { socket } = useSocketStore();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
|
||||
useEffect(() => {
|
||||
console.log(undoStack, redoStack);
|
||||
}, [undoStack, redoStack]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
const keyCombination = detectModifierKeys(event);
|
||||
|
||||
if (keyCombination === 'Ctrl+Z') {
|
||||
handleUndo();
|
||||
}
|
||||
|
||||
if (keyCombination === 'Ctrl+Y') {
|
||||
handleRedo();
|
||||
}
|
||||
};
|
||||
|
||||
if (!toggleView) {
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [toggleView, undoStack, redoStack, socket, selectedVersion, activeModule]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default UndoRedo3DControls;
|
||||
22
app/src/modules/scene/helpers/StatsHelper.tsx
Normal file
22
app/src/modules/scene/helpers/StatsHelper.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Stats } from "@react-three/drei";
|
||||
import { detectModifierKeys } from "../../../utils/shortcutkeys/detectModifierKeys";
|
||||
|
||||
export default function StatsHelper() {
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
const keyCombination = detectModifierKeys(event);
|
||||
if (keyCombination === "F1") {
|
||||
event.preventDefault();
|
||||
setVisible(prev => !prev);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, []);
|
||||
|
||||
return visible ? <Stats className="stats" /> : null;
|
||||
}
|
||||
@@ -14,8 +14,9 @@ import { getAllProjects } from "../../services/dashboard/getAllProjects";
|
||||
import { getUserData } from "../../functions/getUserData";
|
||||
import { useLoadingProgress, useSocketStore } from "../../store/builder/store";
|
||||
import { Color, SRGBColorSpace } from "three";
|
||||
import StatsHelper from "./helpers/StatsHelper";
|
||||
|
||||
export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Comparison Layout' }) {
|
||||
export default function Scene({ layout }: { readonly layout: "Main Layout" | "Comparison Layout"; }) {
|
||||
const map = useMemo(() => [
|
||||
{ name: "forward", keys: ["ArrowUp", "w", "W"] },
|
||||
{ name: "backward", keys: ["ArrowDown", "s", "S"] },
|
||||
@@ -32,28 +33,27 @@ export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Co
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectId && loadingProgress > 1) return;
|
||||
getAllProjects(userId, organization)
|
||||
.then((projects) => {
|
||||
if (!projects || !projects.Projects) return;
|
||||
let project = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId);
|
||||
const canvas = document.getElementById("sceneCanvas")?.getElementsByTagName('canvas')[0];
|
||||
if (!canvas) return;
|
||||
const screenshotDataUrl = (canvas as HTMLCanvasElement)?.toDataURL("image/png");
|
||||
const updateProjects = {
|
||||
projectId: project?.projectUuid,
|
||||
organization,
|
||||
userId,
|
||||
projectName: project?.projectName,
|
||||
thumbnail: screenshotDataUrl,
|
||||
};
|
||||
if (projectSocket) {
|
||||
projectSocket.emit("v1:project:update", updateProjects);
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
getAllProjects(userId, organization).then((projects) => {
|
||||
if (!projects || !projects.Projects) return;
|
||||
let project = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId);
|
||||
const canvas = document.getElementById("sceneCanvas")?.getElementsByTagName("canvas")[0];
|
||||
if (!canvas) return;
|
||||
const screenshotDataUrl = (canvas as HTMLCanvasElement)?.toDataURL("image/png");
|
||||
const updateProjects = {
|
||||
projectId: project?._id,
|
||||
organization,
|
||||
userId,
|
||||
projectName: project?.projectName,
|
||||
thumbnail: screenshotDataUrl,
|
||||
};
|
||||
if (projectSocket) {
|
||||
projectSocket.emit("v1:project:update", updateProjects);
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
// eslint-disable-next-line
|
||||
}, [activeModule, assets, loadingProgress])
|
||||
}, [activeModule, assets, loadingProgress]);
|
||||
|
||||
return (
|
||||
<KeyboardControls map={map}>
|
||||
@@ -62,20 +62,17 @@ export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Co
|
||||
shadows
|
||||
color="#aaaa"
|
||||
eventPrefix="client"
|
||||
onContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
onContextMenu={(e) => { e.preventDefault(); }}
|
||||
performance={{ min: 0.9, max: 1.0 }}
|
||||
onCreated={(e) => {
|
||||
e.scene.background = layout === 'Main Layout' ? null : new Color(0x19191d);
|
||||
}}
|
||||
gl={{ outputColorSpace: SRGBColorSpace, powerPreference: "high-performance", antialias: true, preserveDrawingBuffer: true }}
|
||||
onCreated={(e) => { e.scene.background = layout === "Main Layout" ? null : new Color(0x19191d); }}
|
||||
gl={{ outputColorSpace: SRGBColorSpace, powerPreference: "high-performance", antialias: true }}
|
||||
>
|
||||
<Setup />
|
||||
<Collaboration />
|
||||
<Builder />
|
||||
<Simulation />
|
||||
<Visualization />
|
||||
<StatsHelper />
|
||||
</Canvas>
|
||||
</KeyboardControls>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { createZoneStore, ZoneStoreType } from '../../store/builder/useZoneStore
|
||||
import { createFloorStore, FloorStoreType } from '../../store/builder/useFloorStore';
|
||||
|
||||
import { createUndoRedo2DStore, UndoRedo2DStoreType } from '../../store/builder/useUndoRedo2DStore';
|
||||
import { createUndoRedo3DStore, UndoRedo3DStoreType } from '../../store/builder/useUndoRedo3DStore';
|
||||
|
||||
import { createEventStore, EventStoreType } from '../../store/simulation/useEventsStore';
|
||||
import { createProductStore, ProductStoreType } from '../../store/simulation/useProductStore';
|
||||
@@ -31,6 +32,7 @@ type SceneContextValue = {
|
||||
floorStore: FloorStoreType,
|
||||
|
||||
undoRedo2DStore: UndoRedo2DStoreType,
|
||||
undoRedo3DStore: UndoRedo3DStoreType,
|
||||
|
||||
eventStore: EventStoreType,
|
||||
productStore: ProductStoreType,
|
||||
@@ -45,6 +47,7 @@ type SceneContextValue = {
|
||||
craneStore: CraneStoreType;
|
||||
|
||||
humanEventManagerRef: React.RefObject<HumanEventManagerState>;
|
||||
craneEventManagerRef: React.RefObject<CraneEventManagerState>;
|
||||
|
||||
clearStores: () => void;
|
||||
|
||||
@@ -69,6 +72,7 @@ export function SceneProvider({
|
||||
const floorStore = useMemo(() => createFloorStore(), []);
|
||||
|
||||
const undoRedo2DStore = useMemo(() => createUndoRedo2DStore(), []);
|
||||
const undoRedo3DStore = useMemo(() => createUndoRedo3DStore(), []);
|
||||
|
||||
const eventStore = useMemo(() => createEventStore(), []);
|
||||
const productStore = useMemo(() => createProductStore(), []);
|
||||
@@ -83,6 +87,7 @@ export function SceneProvider({
|
||||
const craneStore = useMemo(() => createCraneStore(), []);
|
||||
|
||||
const humanEventManagerRef = useRef<HumanEventManagerState>({ humanStates: [] });
|
||||
const craneEventManagerRef = useRef<CraneEventManagerState>({ craneStates: [] });
|
||||
|
||||
const clearStores = useMemo(() => () => {
|
||||
assetStore.getState().clearAssets();
|
||||
@@ -92,6 +97,7 @@ export function SceneProvider({
|
||||
zoneStore.getState().clearZones();
|
||||
floorStore.getState().clearFloors();
|
||||
undoRedo2DStore.getState().clearUndoRedo2D();
|
||||
undoRedo3DStore.getState().clearUndoRedo3D();
|
||||
eventStore.getState().clearEvents();
|
||||
productStore.getState().clearProducts();
|
||||
materialStore.getState().clearMaterials();
|
||||
@@ -103,7 +109,8 @@ export function SceneProvider({
|
||||
humanStore.getState().clearHumans();
|
||||
craneStore.getState().clearCranes();
|
||||
humanEventManagerRef.current.humanStates = [];
|
||||
}, [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, undoRedo2DStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore]);
|
||||
craneEventManagerRef.current.craneStates = [];
|
||||
}, [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, undoRedo2DStore, undoRedo3DStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore]);
|
||||
|
||||
const contextValue = useMemo(() => (
|
||||
{
|
||||
@@ -114,6 +121,7 @@ export function SceneProvider({
|
||||
zoneStore,
|
||||
floorStore,
|
||||
undoRedo2DStore,
|
||||
undoRedo3DStore,
|
||||
eventStore,
|
||||
productStore,
|
||||
materialStore,
|
||||
@@ -125,10 +133,11 @@ export function SceneProvider({
|
||||
humanStore,
|
||||
craneStore,
|
||||
humanEventManagerRef,
|
||||
craneEventManagerRef,
|
||||
clearStores,
|
||||
layout
|
||||
}
|
||||
), [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, undoRedo2DStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore, clearStores, layout]);
|
||||
), [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, undoRedo2DStore, undoRedo3DStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore, clearStores, layout]);
|
||||
|
||||
return (
|
||||
<SceneContext.Provider value={contextValue}>
|
||||
|
||||
Reference in New Issue
Block a user