feat: Implement undo and redo functionality for 2D scene controls
- Added useRedoHandler to manage redo actions, including socket communication for wall, floor, zone, and aisle updates. - Added useUndoHandler to manage undo actions, reversing the effects of previous actions with corresponding socket updates. - Created UndoRedo2DControls component to handle keyboard shortcuts for undo (Ctrl+Z) and redo (Ctrl+Y). - Established a Zustand store (useUndoRedo2DStore) to maintain undo and redo stacks, with methods for pushing, popping, and peeking actions.
This commit is contained in:
@@ -19,8 +19,9 @@ function FloorCreator() {
|
|||||||
const { toolMode } = useToolMode();
|
const { toolMode } = useToolMode();
|
||||||
const { activeLayer } = useActiveLayer();
|
const { activeLayer } = useActiveLayer();
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const { floorStore } = useSceneContext();
|
const { floorStore, undoRedo2DStore } = useSceneContext();
|
||||||
const { addFloor, getFloorPointById, getFloorByPoints } = floorStore();
|
const { addFloor, getFloorPointById } = floorStore();
|
||||||
|
const { push2D } = undoRedo2DStore();
|
||||||
const drag = useRef(false);
|
const drag = useRef(false);
|
||||||
const isLeftMouseDown = useRef(false);
|
const isLeftMouseDown = useRef(false);
|
||||||
const { selectedVersionStore } = useVersionContext();
|
const { selectedVersionStore } = useVersionContext();
|
||||||
@@ -103,6 +104,21 @@ function FloorCreator() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
addFloor(floor);
|
addFloor(floor);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Line-Create',
|
||||||
|
point: {
|
||||||
|
type: 'Floor',
|
||||||
|
lineData: floor,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -142,6 +158,21 @@ function FloorCreator() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
addFloor(floor);
|
addFloor(floor);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Line-Create',
|
||||||
|
point: {
|
||||||
|
type: 'Floor',
|
||||||
|
lineData: floor,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -191,6 +222,21 @@ function FloorCreator() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
addFloor(floor);
|
addFloor(floor);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Line-Create',
|
||||||
|
point: {
|
||||||
|
type: 'Floor',
|
||||||
|
lineData: floor,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -243,7 +289,7 @@ function FloorCreator() {
|
|||||||
canvasElement.removeEventListener("click", onMouseClick);
|
canvasElement.removeEventListener("click", onMouseClick);
|
||||||
canvasElement.removeEventListener("contextmenu", onContext);
|
canvasElement.removeEventListener("contextmenu", onContext);
|
||||||
};
|
};
|
||||||
}, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addFloor, getFloorPointById, getFloorByPoints, floorDepth, isBeveled, bevelStrength, sideMaterial, topMaterial, snappedPosition, snappedPoint]);
|
}, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addFloor, getFloorPointById, floorDepth, isBeveled, bevelStrength, sideMaterial, topMaterial, snappedPosition, snappedPoint]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -30,10 +30,11 @@ function Line({ points }: Readonly<LineProps>) {
|
|||||||
const [isDeletable, setIsDeletable] = useState(false);
|
const [isDeletable, setIsDeletable] = useState(false);
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const { toolMode } = useToolMode();
|
const { toolMode } = useToolMode();
|
||||||
const { wallStore, floorStore, zoneStore } = useSceneContext();
|
const { wallStore, floorStore, zoneStore, undoRedo2DStore } = useSceneContext();
|
||||||
|
const { push2D } = undoRedo2DStore();
|
||||||
const { removeWallByPoints, setPosition: setWallPosition, getWallsByPointId } = wallStore();
|
const { removeWallByPoints, setPosition: setWallPosition, getWallsByPointId } = wallStore();
|
||||||
const { removeFloorByPoints, setPosition: setFloorPosition, getFloorsByPointId } = floorStore();
|
const { removeFloorByPoints, setPosition: setFloorPosition, getFloorsByPointId, getFloorsByPoints } = floorStore();
|
||||||
const { removeZoneByPoints, setPosition: setZonePosition, getZonesByPointId } = zoneStore();
|
const { removeZoneByPoints, setPosition: setZonePosition, getZonesByPointId, getZonesByPoints } = zoneStore();
|
||||||
const { userId, organization } = getUserData();
|
const { userId, organization } = getUserData();
|
||||||
const { selectedVersionStore } = useVersionContext();
|
const { selectedVersionStore } = useVersionContext();
|
||||||
const { selectedVersion } = selectedVersionStore();
|
const { selectedVersion } = selectedVersionStore();
|
||||||
@@ -117,10 +118,26 @@ function Line({ points }: Readonly<LineProps>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
socket.emit('v1:model-Wall:delete', data);
|
socket.emit('v1:model-Wall:delete', data);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Line-Delete',
|
||||||
|
point: {
|
||||||
|
type: 'Wall',
|
||||||
|
lineData: removedWall,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setHoveredLine(null);
|
setHoveredLine(null);
|
||||||
}
|
}
|
||||||
if (points[0].pointType === 'Floor' && points[1].pointType === 'Floor') {
|
if (points[0].pointType === 'Floor' && points[1].pointType === 'Floor') {
|
||||||
|
const Floors = getFloorsByPoints(points);
|
||||||
const { removedFloors, updatedFloors } = removeFloorByPoints(points);
|
const { removedFloors, updatedFloors } = removeFloorByPoints(points);
|
||||||
if (removedFloors.length > 0) {
|
if (removedFloors.length > 0) {
|
||||||
removedFloors.forEach(floor => {
|
removedFloors.forEach(floor => {
|
||||||
@@ -143,6 +160,22 @@ function Line({ points }: Readonly<LineProps>) {
|
|||||||
socket.emit('v1:model-Floor:delete', data);
|
socket.emit('v1:model-Floor:delete', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const removedFloorsData = removedFloors.map((floor) => ({
|
||||||
|
type: "Floor" as const,
|
||||||
|
lineData: floor,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Delete',
|
||||||
|
points: removedFloorsData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (updatedFloors.length > 0) {
|
if (updatedFloors.length > 0) {
|
||||||
updatedFloors.forEach(floor => {
|
updatedFloors.forEach(floor => {
|
||||||
@@ -165,11 +198,29 @@ function Line({ points }: Readonly<LineProps>) {
|
|||||||
socket.emit('v1:model-Floor:add', data);
|
socket.emit('v1:model-Floor:add', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatedFloorsData = updatedFloors.map((floor) => ({
|
||||||
|
type: "Floor" as const,
|
||||||
|
lineData: Floors.find(f => f.floorUuid === floor.floorUuid) || floor,
|
||||||
|
newData: floor,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Update',
|
||||||
|
points: updatedFloorsData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setHoveredLine(null);
|
setHoveredLine(null);
|
||||||
}
|
}
|
||||||
if (points[0].pointType === 'Zone' && points[1].pointType === 'Zone') {
|
if (points[0].pointType === 'Zone' && points[1].pointType === 'Zone') {
|
||||||
|
const Zones = getZonesByPoints(points);
|
||||||
const { removedZones, updatedZones } = removeZoneByPoints(points);
|
const { removedZones, updatedZones } = removeZoneByPoints(points);
|
||||||
if (removedZones.length > 0) {
|
if (removedZones.length > 0) {
|
||||||
removedZones.forEach(zone => {
|
removedZones.forEach(zone => {
|
||||||
@@ -192,6 +243,22 @@ function Line({ points }: Readonly<LineProps>) {
|
|||||||
socket.emit('v1:zone:delete', data);
|
socket.emit('v1:zone:delete', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const removedZonesData = removedZones.map((zone) => ({
|
||||||
|
type: "Zone" as const,
|
||||||
|
lineData: zone,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Delete',
|
||||||
|
points: removedZonesData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (updatedZones.length > 0) {
|
if (updatedZones.length > 0) {
|
||||||
updatedZones.forEach(zone => {
|
updatedZones.forEach(zone => {
|
||||||
@@ -214,7 +281,26 @@ function Line({ points }: Readonly<LineProps>) {
|
|||||||
socket.emit('v1:zone:add', data);
|
socket.emit('v1:zone:add', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatedZonesData = updatedZones.map((zone) => ({
|
||||||
|
type: "Zone" as const,
|
||||||
|
lineData: Zones.find(z => z.zoneUuid === zone.zoneUuid) || zone,
|
||||||
|
newData: zone,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Update',
|
||||||
|
points: updatedZonesData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setHoveredLine(null);
|
||||||
}
|
}
|
||||||
handleCanvasCursors('default');
|
handleCanvasCursors('default');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,13 +32,14 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
|
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const { toolMode } = useToolMode();
|
const { toolMode } = useToolMode();
|
||||||
const { aisleStore, wallStore, floorStore, zoneStore } = useSceneContext();
|
const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore } = useSceneContext();
|
||||||
|
const { push2D } = undoRedo2DStore();
|
||||||
const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore();
|
const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore();
|
||||||
const { setPosition: setWallPosition, removePoint: removeWallPoint, getWallsByPointId } = wallStore();
|
const { setPosition: setWallPosition, removePoint: removeWallPoint, getWallsByPointId } = wallStore();
|
||||||
const { setPosition: setFloorPosition, removePoint: removeFloorPoint, getFloorsByPointId } = floorStore();
|
const { setPosition: setFloorPosition, removePoint: removeFloorPoint, getFloorsByPointId } = floorStore();
|
||||||
const { setPosition: setZonePosition, removePoint: removeZonePoint, getZonesByPointId } = zoneStore();
|
const { setPosition: setZonePosition, removePoint: removeZonePoint, getZonesByPointId } = zoneStore();
|
||||||
const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle, snapFloorPoint, snapFloorAngle, snapZonePoint, snapZoneAngle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position });
|
const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle, snapFloorPoint, snapFloorAngle, snapZonePoint, snapZoneAngle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position });
|
||||||
const { hoveredPoint,hoveredLine, setHoveredPoint } = useBuilderStore();
|
const { hoveredPoint, hoveredLine, setHoveredPoint } = useBuilderStore();
|
||||||
const { selectedPoints } = useSelectedPoints();
|
const { selectedPoints } = useSelectedPoints();
|
||||||
const { userId, organization } = getUserData();
|
const { userId, organization } = getUserData();
|
||||||
const { selectedVersionStore } = useVersionContext();
|
const { selectedVersionStore } = useVersionContext();
|
||||||
@@ -47,6 +48,13 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
|
const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
|
||||||
const colors = getColor(point);
|
const colors = getColor(point);
|
||||||
|
|
||||||
|
const [initialPositions, setInitialPositions] = useState<{
|
||||||
|
aisles?: Aisle[],
|
||||||
|
walls?: Wall[],
|
||||||
|
floors?: Floor[],
|
||||||
|
zones?: Zone[]
|
||||||
|
}>({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleCanvasCursors('default');
|
handleCanvasCursors('default');
|
||||||
}, [toolMode])
|
}, [toolMode])
|
||||||
@@ -152,6 +160,20 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
const currentPosition = new THREE.Vector3(...point.position);
|
const currentPosition = new THREE.Vector3(...point.position);
|
||||||
const offset = new THREE.Vector3().subVectors(currentPosition, hit);
|
const offset = new THREE.Vector3().subVectors(currentPosition, hit);
|
||||||
setDragOffset(offset);
|
setDragOffset(offset);
|
||||||
|
|
||||||
|
if (point.pointType === 'Aisle') {
|
||||||
|
const aisles = getAislesByPointId(point.pointUuid);
|
||||||
|
setInitialPositions({ aisles });
|
||||||
|
} else if (point.pointType === 'Wall') {
|
||||||
|
const walls = getWallsByPointId(point.pointUuid);
|
||||||
|
setInitialPositions({ walls });
|
||||||
|
} else if (point.pointType === 'Floor') {
|
||||||
|
const floors = getFloorsByPointId(point.pointUuid);
|
||||||
|
setInitialPositions({ floors });
|
||||||
|
} else if (point.pointType === 'Zone') {
|
||||||
|
const zones = getZonesByPointId(point.pointUuid);
|
||||||
|
setInitialPositions({ zones });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -159,6 +181,7 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
handleCanvasCursors('default');
|
handleCanvasCursors('default');
|
||||||
setDragOffset(null);
|
setDragOffset(null);
|
||||||
if (toolMode !== 'move') return;
|
if (toolMode !== 'move') return;
|
||||||
|
|
||||||
if (point.pointType === 'Aisle') {
|
if (point.pointType === 'Aisle') {
|
||||||
const updatedAisles = getAislesByPointId(point.pointUuid);
|
const updatedAisles = getAislesByPointId(point.pointUuid);
|
||||||
if (updatedAisles.length > 0 && projectId) {
|
if (updatedAisles.length > 0 && projectId) {
|
||||||
@@ -180,6 +203,23 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
type: updatedAisle.type
|
type: updatedAisle.type
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (initialPositions.aisles && initialPositions.aisles.length > 0) {
|
||||||
|
const updatedPoints = initialPositions.aisles.map((aisle) => ({
|
||||||
|
type: "Aisle" as const,
|
||||||
|
lineData: aisle,
|
||||||
|
newData: updatedAisles.find(a => a.aisleUuid === aisle.aisleUuid),
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [{
|
||||||
|
actionType: 'Lines-Update',
|
||||||
|
points: updatedPoints,
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (point.pointType === 'Wall') {
|
} else if (point.pointType === 'Wall') {
|
||||||
const updatedWalls = getWallsByPointId(point.pointUuid);
|
const updatedWalls = getWallsByPointId(point.pointUuid);
|
||||||
@@ -203,6 +243,23 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
socket.emit('v1:model-Wall:add', data);
|
socket.emit('v1:model-Wall:add', data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (initialPositions.walls && initialPositions.walls.length > 0) {
|
||||||
|
const updatedPoints = initialPositions.walls.map((wall) => ({
|
||||||
|
type: "Wall" as const,
|
||||||
|
lineData: wall,
|
||||||
|
newData: updatedWalls.find(w => w.wallUuid === wall.wallUuid),
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [{
|
||||||
|
actionType: 'Lines-Update',
|
||||||
|
points: updatedPoints,
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (point.pointType === 'Floor') {
|
} else if (point.pointType === 'Floor') {
|
||||||
const updatedFloors = getFloorsByPointId(point.pointUuid);
|
const updatedFloors = getFloorsByPointId(point.pointUuid);
|
||||||
if (updatedFloors && updatedFloors.length > 0 && projectId) {
|
if (updatedFloors && updatedFloors.length > 0 && projectId) {
|
||||||
@@ -225,6 +282,23 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
socket.emit('v1:model-Floor:add', data);
|
socket.emit('v1:model-Floor:add', data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (initialPositions.floors && initialPositions.floors.length > 0) {
|
||||||
|
const updatedPoints = initialPositions.floors.map((floor) => ({
|
||||||
|
type: "Floor" as const,
|
||||||
|
lineData: floor,
|
||||||
|
newData: updatedFloors.find(f => f.floorUuid === floor.floorUuid),
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [{
|
||||||
|
actionType: 'Lines-Update',
|
||||||
|
points: updatedPoints,
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (point.pointType === 'Zone') {
|
} else if (point.pointType === 'Zone') {
|
||||||
const updatedZones = getZonesByPointId(point.pointUuid);
|
const updatedZones = getZonesByPointId(point.pointUuid);
|
||||||
if (updatedZones && updatedZones.length > 0 && projectId) {
|
if (updatedZones && updatedZones.length > 0 && projectId) {
|
||||||
@@ -247,13 +321,33 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
socket.emit('v1:zone:add', data);
|
socket.emit('v1:zone:add', data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (initialPositions.zones && initialPositions.zones.length > 0) {
|
||||||
|
const updatedPoints = initialPositions.zones.map((zone) => ({
|
||||||
|
type: "Zone" as const,
|
||||||
|
lineData: zone,
|
||||||
|
newData: updatedZones.find(z => z.zoneUuid === zone.zoneUuid),
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [{
|
||||||
|
actionType: 'Lines-Update',
|
||||||
|
points: updatedPoints,
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setInitialPositions({});
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePointClick = (point: Point) => {
|
const handlePointClick = (point: Point) => {
|
||||||
if (toolMode === '2D-Delete') {
|
if (toolMode === '2D-Delete') {
|
||||||
if (point.pointType === 'Aisle') {
|
if (point.pointType === 'Aisle') {
|
||||||
const removedAisles = removeAislePoint(point.pointUuid);
|
const removedAisles = removeAislePoint(point.pointUuid);
|
||||||
|
setHoveredPoint(null);
|
||||||
if (removedAisles.length > 0) {
|
if (removedAisles.length > 0) {
|
||||||
removedAisles.forEach(aisle => {
|
removedAisles.forEach(aisle => {
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
@@ -273,9 +367,25 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
socket.emit('v1:model-aisle:delete', data);
|
socket.emit('v1:model-aisle:delete', data);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setHoveredPoint(null);
|
|
||||||
|
const removedAislesData = removedAisles.map((aisle) => ({
|
||||||
|
type: "Aisle" as const,
|
||||||
|
lineData: aisle,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Delete',
|
||||||
|
points: removedAislesData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (point.pointType === 'Wall') {
|
if (point.pointType === 'Wall') {
|
||||||
@@ -302,9 +412,26 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
socket.emit('v1:model-Wall:delete', data);
|
socket.emit('v1:model-Wall:delete', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const removedWallsData = removedWalls.map((wall) => ({
|
||||||
|
type: "Wall" as const,
|
||||||
|
lineData: wall,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Delete',
|
||||||
|
points: removedWallsData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (point.pointType === 'Floor') {
|
if (point.pointType === 'Floor') {
|
||||||
|
const Floors = getFloorsByPointId(point.pointUuid);
|
||||||
const { removedFloors, updatedFloors } = removeFloorPoint(point.pointUuid);
|
const { removedFloors, updatedFloors } = removeFloorPoint(point.pointUuid);
|
||||||
setHoveredPoint(null);
|
setHoveredPoint(null);
|
||||||
if (removedFloors.length > 0) {
|
if (removedFloors.length > 0) {
|
||||||
@@ -328,6 +455,22 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
socket.emit('v1:model-Floor:delete', data);
|
socket.emit('v1:model-Floor:delete', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const removedFloorsData = removedFloors.map((floor) => ({
|
||||||
|
type: "Floor" as const,
|
||||||
|
lineData: floor,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Delete',
|
||||||
|
points: removedFloorsData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (updatedFloors.length > 0) {
|
if (updatedFloors.length > 0) {
|
||||||
updatedFloors.forEach(floor => {
|
updatedFloors.forEach(floor => {
|
||||||
@@ -350,9 +493,27 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
socket.emit('v1:model-Floor:add', data);
|
socket.emit('v1:model-Floor:add', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatedFloorsData = updatedFloors.map((floor) => ({
|
||||||
|
type: "Floor" as const,
|
||||||
|
lineData: Floors.find(f => f.floorUuid === floor.floorUuid) || floor,
|
||||||
|
newData: floor,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Update',
|
||||||
|
points: updatedFloorsData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (point.pointType === 'Zone') {
|
if (point.pointType === 'Zone') {
|
||||||
|
const Zones = getZonesByPointId(point.pointUuid);
|
||||||
const { removedZones, updatedZones } = removeZonePoint(point.pointUuid);
|
const { removedZones, updatedZones } = removeZonePoint(point.pointUuid);
|
||||||
setHoveredPoint(null);
|
setHoveredPoint(null);
|
||||||
if (removedZones.length > 0) {
|
if (removedZones.length > 0) {
|
||||||
@@ -376,6 +537,22 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
socket.emit('v1:zone:delete', data);
|
socket.emit('v1:zone:delete', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const removedZonesData = removedZones.map((zone) => ({
|
||||||
|
type: "Zone" as const,
|
||||||
|
lineData: zone,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Delete',
|
||||||
|
points: removedZonesData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (updatedZones.length > 0) {
|
if (updatedZones.length > 0) {
|
||||||
updatedZones.forEach(zone => {
|
updatedZones.forEach(zone => {
|
||||||
@@ -398,6 +575,23 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
socket.emit('v1:zone:add', data);
|
socket.emit('v1:zone:add', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatedZonesData = updatedZones.map((zone) => ({
|
||||||
|
type: "Zone" as const,
|
||||||
|
lineData: Zones.find(z => z.zoneUuid === zone.zoneUuid) || zone,
|
||||||
|
newData: zone,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Update',
|
||||||
|
points: updatedZonesData
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleCanvasCursors('default');
|
handleCanvasCursors('default');
|
||||||
@@ -422,7 +616,6 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!isSelected ?
|
{!isSelected ?
|
||||||
@@ -453,7 +646,7 @@ function Point({ point }: { readonly point: Point }) {
|
|||||||
onPointerOut={() => {
|
onPointerOut={() => {
|
||||||
if (hoveredPoint) {
|
if (hoveredPoint) {
|
||||||
setHoveredPoint(null);
|
setHoveredPoint(null);
|
||||||
if(!hoveredLine){
|
if (!hoveredLine) {
|
||||||
handleCanvasCursors('default');
|
handleCanvasCursors('default');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,9 @@ function WallCreator() {
|
|||||||
const { toolMode } = useToolMode();
|
const { toolMode } = useToolMode();
|
||||||
const { activeLayer } = useActiveLayer();
|
const { activeLayer } = useActiveLayer();
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const { wallStore } = useSceneContext();
|
const { wallStore, undoRedo2DStore } = useSceneContext();
|
||||||
const { addWall, getWallPointById, removeWall, getWallByPoints } = wallStore();
|
const { addWall, getWallPointById, removeWall, getWallByPoints } = wallStore();
|
||||||
|
const { push2D } = undoRedo2DStore();
|
||||||
const drag = useRef(false);
|
const drag = useRef(false);
|
||||||
const isLeftMouseDown = useRef(false);
|
const isLeftMouseDown = useRef(false);
|
||||||
const { selectedVersionStore } = useVersionContext();
|
const { selectedVersionStore } = useVersionContext();
|
||||||
@@ -91,6 +92,7 @@ function WallCreator() {
|
|||||||
const closestPoint = new THREE.Vector3().lerpVectors(point1Vec, point2Vec, t);
|
const closestPoint = new THREE.Vector3().lerpVectors(point1Vec, point2Vec, t);
|
||||||
|
|
||||||
removeWall(wall.wallUuid);
|
removeWall(wall.wallUuid);
|
||||||
|
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -142,6 +144,7 @@ function WallCreator() {
|
|||||||
wallHeight: wallHeight,
|
wallHeight: wallHeight,
|
||||||
decals: []
|
decals: []
|
||||||
}
|
}
|
||||||
|
|
||||||
addWall(wall2);
|
addWall(wall2);
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -171,8 +174,36 @@ function WallCreator() {
|
|||||||
wallHeight: wallHeight,
|
wallHeight: wallHeight,
|
||||||
decals: []
|
decals: []
|
||||||
}
|
}
|
||||||
|
|
||||||
addWall(wall3);
|
addWall(wall3);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Create',
|
||||||
|
points: [
|
||||||
|
{
|
||||||
|
type: 'Wall',
|
||||||
|
lineData: wall3,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}, {
|
||||||
|
type: 'Wall',
|
||||||
|
lineData: wall2,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
actionType: 'Line-Delete',
|
||||||
|
point: {
|
||||||
|
type: 'Wall',
|
||||||
|
lineData: wall,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
// API
|
// API
|
||||||
|
|
||||||
// if (projectId) {
|
// if (projectId) {
|
||||||
@@ -202,7 +233,8 @@ function WallCreator() {
|
|||||||
wallThickness: wallThickness,
|
wallThickness: wallThickness,
|
||||||
wallHeight: wallHeight,
|
wallHeight: wallHeight,
|
||||||
decals: []
|
decals: []
|
||||||
};
|
}
|
||||||
|
|
||||||
addWall(wall1);
|
addWall(wall1);
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -232,6 +264,7 @@ function WallCreator() {
|
|||||||
wallHeight: wallHeight,
|
wallHeight: wallHeight,
|
||||||
decals: []
|
decals: []
|
||||||
}
|
}
|
||||||
|
|
||||||
addWall(wall2);
|
addWall(wall2);
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -261,8 +294,40 @@ function WallCreator() {
|
|||||||
wallHeight: wallHeight,
|
wallHeight: wallHeight,
|
||||||
decals: []
|
decals: []
|
||||||
}
|
}
|
||||||
|
|
||||||
addWall(wall3);
|
addWall(wall3);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Lines-Create',
|
||||||
|
points: [
|
||||||
|
{
|
||||||
|
type: 'Wall',
|
||||||
|
lineData: wall3,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}, {
|
||||||
|
type: 'Wall',
|
||||||
|
lineData: wall1,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}, {
|
||||||
|
type: 'Wall',
|
||||||
|
lineData: wall2,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
actionType: 'Line-Delete',
|
||||||
|
point: {
|
||||||
|
type: 'Wall',
|
||||||
|
lineData: wall,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
// API
|
// API
|
||||||
|
|
||||||
// if (projectId) {
|
// if (projectId) {
|
||||||
@@ -328,9 +393,24 @@ function WallCreator() {
|
|||||||
wallThickness: wallThickness,
|
wallThickness: wallThickness,
|
||||||
wallHeight: wallHeight,
|
wallHeight: wallHeight,
|
||||||
decals: []
|
decals: []
|
||||||
};
|
}
|
||||||
|
|
||||||
addWall(wall);
|
addWall(wall);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Line-Create',
|
||||||
|
point: {
|
||||||
|
type: 'Wall',
|
||||||
|
lineData: wall,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
// API
|
// API
|
||||||
|
|
||||||
// if (projectId) {
|
// if (projectId) {
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ function ZoneCreator() {
|
|||||||
const { toolMode } = useToolMode();
|
const { toolMode } = useToolMode();
|
||||||
const { activeLayer } = useActiveLayer();
|
const { activeLayer } = useActiveLayer();
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const { zoneStore } = useSceneContext();
|
const { zoneStore, undoRedo2DStore } = useSceneContext();
|
||||||
const { zones, addZone, getZonePointById, getZoneByPoints } = zoneStore();
|
const { addZone, getZonePointById } = zoneStore();
|
||||||
|
const { push2D } = undoRedo2DStore();
|
||||||
const drag = useRef(false);
|
const drag = useRef(false);
|
||||||
const isLeftMouseDown = useRef(false);
|
const isLeftMouseDown = useRef(false);
|
||||||
const { selectedVersionStore } = useVersionContext();
|
const { selectedVersionStore } = useVersionContext();
|
||||||
@@ -102,6 +103,21 @@ function ZoneCreator() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
addZone(zone);
|
addZone(zone);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Line-Create',
|
||||||
|
point: {
|
||||||
|
type: 'Zone',
|
||||||
|
lineData: zone,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -139,6 +155,21 @@ function ZoneCreator() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
addZone(zone);
|
addZone(zone);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Line-Create',
|
||||||
|
point: {
|
||||||
|
type: 'Zone',
|
||||||
|
lineData: zone,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -186,6 +217,21 @@ function ZoneCreator() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
addZone(zone);
|
addZone(zone);
|
||||||
|
|
||||||
|
push2D({
|
||||||
|
type: 'Draw',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'Line-Create',
|
||||||
|
point: {
|
||||||
|
type: 'Zone',
|
||||||
|
lineData: zone,
|
||||||
|
timeStamp: new Date().toISOString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@@ -238,7 +284,7 @@ function ZoneCreator() {
|
|||||||
canvasElement.removeEventListener("click", onMouseClick);
|
canvasElement.removeEventListener("click", onMouseClick);
|
||||||
canvasElement.removeEventListener("contextmenu", onContext);
|
canvasElement.removeEventListener("contextmenu", onContext);
|
||||||
};
|
};
|
||||||
}, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addZone, getZonePointById, getZoneByPoints, zoneColor, zoneHeight, snappedPosition, snappedPoint]);
|
}, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addZone, getZonePointById, zoneColor, zoneHeight, snappedPosition, snappedPoint]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import TransformControl from "./transformControls/transformControls";
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { getUserData } from "../../../functions/getUserData";
|
import { getUserData } from "../../../functions/getUserData";
|
||||||
import SelectionControls2D from "./selectionControls/selection2D/selectionControls2D";
|
import SelectionControls2D from "./selectionControls/selection2D/selectionControls2D";
|
||||||
|
import UndoRedo2DControls from "./undoRedoControls/undoRedo2D/undoRedo2DControls";
|
||||||
|
|
||||||
export default function Controls() {
|
export default function Controls() {
|
||||||
const controlsRef = useRef<CameraControls>(null);
|
const controlsRef = useRef<CameraControls>(null);
|
||||||
@@ -142,6 +143,8 @@ export default function Controls() {
|
|||||||
|
|
||||||
<SelectionControls2D />
|
<SelectionControls2D />
|
||||||
|
|
||||||
|
<UndoRedo2DControls />
|
||||||
|
|
||||||
<TransformControl />
|
<TransformControl />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -0,0 +1,355 @@
|
|||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { getUserData } from "../../../../../functions/getUserData";
|
||||||
|
import { useVersionContext } from "../../../../builder/version/versionContext";
|
||||||
|
import { useSceneContext } from "../../../sceneContext";
|
||||||
|
import { useSocketStore } from "../../../../../store/builder/store";
|
||||||
|
|
||||||
|
// import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
|
||||||
|
// import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
|
||||||
|
|
||||||
|
// import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
|
||||||
|
// import { deleteZoneApi } from "../../../../../services/factoryBuilder/zone/deleteZoneApi";
|
||||||
|
|
||||||
|
// import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
|
||||||
|
// import { deleteFloorApi } from "../../../../../services/factoryBuilder/floor/deleteFloorApi";
|
||||||
|
|
||||||
|
// import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
|
||||||
|
// import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
|
||||||
|
|
||||||
|
function useRedoHandler() {
|
||||||
|
const { undoRedo2DStore, wallStore, floorStore, zoneStore, aisleStore } = useSceneContext();
|
||||||
|
const { redo2D, peekRedo2D } = undoRedo2DStore();
|
||||||
|
const { addWall, removeWall, updateWall } = wallStore();
|
||||||
|
const { addFloor, removeFloor, updateFloor } = floorStore();
|
||||||
|
const { addZone, removeZone, updateZone } = zoneStore();
|
||||||
|
const { addAisle, removeAisle, updateAisle } = aisleStore();
|
||||||
|
const { selectedVersionStore } = useVersionContext();
|
||||||
|
const { selectedVersion } = selectedVersionStore();
|
||||||
|
const { userId, organization } = getUserData();
|
||||||
|
const { projectId } = useParams();
|
||||||
|
const { socket } = useSocketStore();
|
||||||
|
|
||||||
|
const handleRedo = () => {
|
||||||
|
const redoData = peekRedo2D();
|
||||||
|
if (!redoData) return;
|
||||||
|
|
||||||
|
if (redoData.type === 'Draw') {
|
||||||
|
const { actions } = redoData;
|
||||||
|
|
||||||
|
actions.forEach(action => {
|
||||||
|
const { actionType } = action;
|
||||||
|
|
||||||
|
if ('point' in action) {
|
||||||
|
const point = action.point;
|
||||||
|
|
||||||
|
if (actionType === 'Line-Create') {
|
||||||
|
handleCreate(point);
|
||||||
|
} else if (actionType === 'Line-Update') {
|
||||||
|
handleUpdate(point);
|
||||||
|
} else if (actionType === 'Line-Delete') {
|
||||||
|
handleRemove(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ('points' in action) {
|
||||||
|
const points = action.points;
|
||||||
|
|
||||||
|
if (actionType === 'Lines-Create') {
|
||||||
|
points.forEach(handleCreate);
|
||||||
|
} else if (actionType === 'Lines-Update') {
|
||||||
|
points.forEach(handleUpdate);
|
||||||
|
} else if (actionType === 'Lines-Delete') {
|
||||||
|
points.forEach(handleRemove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (redoData.type === 'UI') {
|
||||||
|
// Handle UI actions if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
redo2D();
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdate = (point: UndoRedo2DDataTypeSchema) => {
|
||||||
|
if (!point.newData) return;
|
||||||
|
switch (point.type) {
|
||||||
|
case 'Wall': updateWallFromBackend(point.newData.wallUuid, point.newData); break;
|
||||||
|
case 'Floor': updateFloorFromBackend(point.newData.floorUuid, point.newData); break;
|
||||||
|
case 'Zone': updateZoneFromBackend(point.newData.zoneUuid, point.newData); break;
|
||||||
|
case 'Aisle': updateAisleFromBackend(point.newData.aisleUuid, point.newData); break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createWallFromBackend = (wallData: Wall) => {
|
||||||
|
addWall(wallData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertWallApi(projectId, selectedVersion?.versionId || '', wallData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
wallData: wallData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Wall:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeWallFromBackend = (wallUuid: string) => {
|
||||||
|
removeWall(wallUuid);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// deleteWallApi(projectId, selectedVersion?.versionId || '', wallUuid);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
wallUuid: wallUuid,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Wall:delete', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateWallFromBackend = (wallUuid: string, updatedData: Wall) => {
|
||||||
|
updateWall(wallUuid, updatedData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
wallData: updatedData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Wall:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFloorFromBackend = (floorData: Floor) => {
|
||||||
|
addFloor(floorData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floorData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
floorData: floorData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Floor:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeFloorFromBackend = (floorUuid: string) => {
|
||||||
|
removeFloor(floorUuid);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// deleteFloorApi(projectId, selectedVersion?.versionId || '', floorUuid);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
floorUuid: floorUuid,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Floor:delete', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateFloorFromBackend = (floorUuid: string, updatedData: Floor) => {
|
||||||
|
updateFloor(floorUuid, updatedData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
floorData: updatedData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Floor:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createZoneFromBackend = (zoneData: Zone) => {
|
||||||
|
addZone(zoneData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zoneData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
zoneData: zoneData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:zone:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeZoneFromBackend = (zoneUuid: string) => {
|
||||||
|
removeZone(zoneUuid);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// deleteZoneApi(projectId, selectedVersion?.versionId || '', zoneUuid);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
zoneUuid,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:zone:delete', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateZoneFromBackend = (zoneUuid: string, updatedData: Zone) => {
|
||||||
|
updateZone(zoneUuid, updatedData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
zoneData: updatedData,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:zone:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createAisleFromBackend = (aisleData: Aisle) => {
|
||||||
|
addAisle(aisleData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(projectId, selectedVersion?.versionId || '', aisleData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
aisleData,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeAisleFromBackend = (aisleUuid: string) => {
|
||||||
|
removeAisle(aisleUuid);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// deleteAisleApi(projectId, selectedVersion?.versionId || '', aisleUuid);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
aisleUuid,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:delete', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateAisleFromBackend = (aisleUuid: string, updatedData: Aisle) => {
|
||||||
|
updateAisle(aisleUuid, updatedData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(projectId, selectedVersion?.versionId || '', updatedData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
aisleData: updatedData,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return { handleRedo };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useRedoHandler;
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { getUserData } from "../../../../../functions/getUserData";
|
||||||
|
import { useVersionContext } from "../../../../builder/version/versionContext";
|
||||||
|
import { useSceneContext } from "../../../sceneContext";
|
||||||
|
import { useSocketStore } from "../../../../../store/builder/store";
|
||||||
|
|
||||||
|
// import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
|
||||||
|
// import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
|
||||||
|
|
||||||
|
// import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
|
||||||
|
// import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
|
||||||
|
|
||||||
|
// import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
|
||||||
|
// import { deleteFloorApi } from "../../../../../services/factoryBuilder/floor/deleteFloorApi";
|
||||||
|
|
||||||
|
// import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
|
||||||
|
// import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
|
||||||
|
|
||||||
|
function useUndoHandler() {
|
||||||
|
const { undoRedo2DStore, wallStore, floorStore, zoneStore, aisleStore } = useSceneContext();
|
||||||
|
const { undo2D, peekUndo2D } = undoRedo2DStore();
|
||||||
|
const { addWall, removeWall, updateWall } = wallStore();
|
||||||
|
const { addFloor, removeFloor, updateFloor } = floorStore();
|
||||||
|
const { addZone, removeZone, updateZone } = zoneStore();
|
||||||
|
const { addAisle, removeAisle, updateAisle } = aisleStore();
|
||||||
|
const { selectedVersionStore } = useVersionContext();
|
||||||
|
const { selectedVersion } = selectedVersionStore();
|
||||||
|
const { userId, organization } = getUserData();
|
||||||
|
const { projectId } = useParams();
|
||||||
|
const { socket } = useSocketStore();
|
||||||
|
|
||||||
|
const handleUndo = () => {
|
||||||
|
const unDoData = peekUndo2D();
|
||||||
|
if (!unDoData) return;
|
||||||
|
|
||||||
|
if (unDoData.type === 'Draw') {
|
||||||
|
const { actions } = unDoData;
|
||||||
|
|
||||||
|
actions.forEach(action => {
|
||||||
|
const { actionType } = action;
|
||||||
|
|
||||||
|
if ('point' in action) {
|
||||||
|
const point = action.point;
|
||||||
|
|
||||||
|
if (actionType === 'Line-Create') {
|
||||||
|
handleRemove(point);
|
||||||
|
} else if (actionType === 'Line-Update') {
|
||||||
|
handleUpdate(point);
|
||||||
|
} else if (actionType === 'Line-Delete') {
|
||||||
|
handleCreate(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ('points' in action) {
|
||||||
|
const points = action.points;
|
||||||
|
|
||||||
|
if (actionType === 'Lines-Create') {
|
||||||
|
points.forEach(handleRemove);
|
||||||
|
} else if (actionType === 'Lines-Update') {
|
||||||
|
points.forEach(handleUpdate);
|
||||||
|
} else if (actionType === 'Lines-Delete') {
|
||||||
|
points.forEach(handleCreate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (unDoData.type === 'UI') {
|
||||||
|
// Handle UI actions if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const createWallFromBackend = (wallData: Wall) => {
|
||||||
|
addWall(wallData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertWallApi(projectId, selectedVersion?.versionId || '', wallData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
wallData: wallData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Wall:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeWallFromBackend = (wallUuid: string) => {
|
||||||
|
removeWall(wallUuid);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// deleteWallApi(projectId, selectedVersion?.versionId || '', wallUuid);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
wallUuid: wallUuid,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Wall:delete', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateWallFromBackend = (wallUuid: string, updatedData: Wall) => {
|
||||||
|
updateWall(wallUuid, updatedData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
wallData: updatedData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Wall:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFloorFromBackend = (floorData: Floor) => {
|
||||||
|
addFloor(floorData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertFloorApi(projectId, selectedVersion?.versionId || '', floorData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
floorData: floorData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Floor:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeFloorFromBackend = (floorUuid: string) => {
|
||||||
|
removeFloor(floorUuid);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// deleteFloorApi(projectId, selectedVersion?.versionId || '', floorUuid);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
floorUuid: floorUuid,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Floor:delete', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateFloorFromBackend = (floorUuid: string, updatedData: Floor) => {
|
||||||
|
updateFloor(floorUuid, updatedData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
floorData: updatedData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:model-Floor:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createZoneFromBackend = (zoneData: Zone) => {
|
||||||
|
addZone(zoneData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertZoneApi(projectId, selectedVersion?.versionId || '', zoneData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
zoneData: zoneData,
|
||||||
|
projectId: projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId: userId,
|
||||||
|
organization: organization
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v1:zone:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeZoneFromBackend = (zoneUuid: string) => {
|
||||||
|
removeZone(zoneUuid);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// deleteZoneApi(projectId, selectedVersion?.versionId || '', zoneUuid);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
zoneUuid,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:zone:delete', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateZoneFromBackend = (zoneUuid: string, updatedData: Zone) => {
|
||||||
|
updateZone(zoneUuid, updatedData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
zoneData: updatedData,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:zone:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createAisleFromBackend = (aisleData: Aisle) => {
|
||||||
|
addAisle(aisleData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(projectId, selectedVersion?.versionId || '', aisleData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
aisleData,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeAisleFromBackend = (aisleUuid: string) => {
|
||||||
|
removeAisle(aisleUuid);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// deleteAisleApi(projectId, selectedVersion?.versionId || '', aisleUuid);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
aisleUuid,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:delete', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateAisleFromBackend = (aisleUuid: string, updatedData: Aisle) => {
|
||||||
|
updateAisle(aisleUuid, updatedData);
|
||||||
|
if (projectId) {
|
||||||
|
// API
|
||||||
|
|
||||||
|
// upsertAisleApi(projectId, selectedVersion?.versionId || '', updatedData);
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
aisleData: updatedData,
|
||||||
|
projectId,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
userId,
|
||||||
|
organization
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:model-aisle:add', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return { handleUndo };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useUndoHandler;
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
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 useUndoHandler from '../handlers/useUndoHandler';
|
||||||
|
import useRedoHandler from '../handlers/useRedoHandler';
|
||||||
|
|
||||||
|
function UndoRedo2DControls() {
|
||||||
|
const { undoRedo2DStore } = useSceneContext();
|
||||||
|
const { undoStack, redoStack } = undoRedo2DStore();
|
||||||
|
const { toggleView } = useToggleView();
|
||||||
|
const { handleUndo } = useUndoHandler();
|
||||||
|
const { handleRedo } = useRedoHandler();
|
||||||
|
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]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UndoRedo2DControls;
|
||||||
@@ -7,6 +7,8 @@ import { createAisleStore, AisleStoreType } from '../../store/builder/useAisleSt
|
|||||||
import { createZoneStore, ZoneStoreType } from '../../store/builder/useZoneStore';
|
import { createZoneStore, ZoneStoreType } from '../../store/builder/useZoneStore';
|
||||||
import { createFloorStore, FloorStoreType } from '../../store/builder/useFloorStore';
|
import { createFloorStore, FloorStoreType } from '../../store/builder/useFloorStore';
|
||||||
|
|
||||||
|
import { createUndoRedo2DStore, UndoRedo2DStoreType } from '../../store/builder/useUndoRedo2DStore';
|
||||||
|
|
||||||
import { createEventStore, EventStoreType } from '../../store/simulation/useEventsStore';
|
import { createEventStore, EventStoreType } from '../../store/simulation/useEventsStore';
|
||||||
import { createProductStore, ProductStoreType } from '../../store/simulation/useProductStore';
|
import { createProductStore, ProductStoreType } from '../../store/simulation/useProductStore';
|
||||||
|
|
||||||
@@ -27,6 +29,8 @@ type SceneContextValue = {
|
|||||||
zoneStore: ZoneStoreType,
|
zoneStore: ZoneStoreType,
|
||||||
floorStore: FloorStoreType,
|
floorStore: FloorStoreType,
|
||||||
|
|
||||||
|
undoRedo2DStore: UndoRedo2DStoreType,
|
||||||
|
|
||||||
eventStore: EventStoreType,
|
eventStore: EventStoreType,
|
||||||
productStore: ProductStoreType,
|
productStore: ProductStoreType,
|
||||||
|
|
||||||
@@ -62,6 +66,8 @@ export function SceneProvider({
|
|||||||
const zoneStore = useMemo(() => createZoneStore(), []);
|
const zoneStore = useMemo(() => createZoneStore(), []);
|
||||||
const floorStore = useMemo(() => createFloorStore(), []);
|
const floorStore = useMemo(() => createFloorStore(), []);
|
||||||
|
|
||||||
|
const undoRedo2DStore = useMemo(() => createUndoRedo2DStore(), []);
|
||||||
|
|
||||||
const eventStore = useMemo(() => createEventStore(), []);
|
const eventStore = useMemo(() => createEventStore(), []);
|
||||||
const productStore = useMemo(() => createProductStore(), []);
|
const productStore = useMemo(() => createProductStore(), []);
|
||||||
|
|
||||||
@@ -82,6 +88,7 @@ export function SceneProvider({
|
|||||||
aisleStore.getState().clearAisles();
|
aisleStore.getState().clearAisles();
|
||||||
zoneStore.getState().clearZones();
|
zoneStore.getState().clearZones();
|
||||||
floorStore.getState().clearFloors();
|
floorStore.getState().clearFloors();
|
||||||
|
undoRedo2DStore.getState().clearUndoRedo2D();
|
||||||
eventStore.getState().clearEvents();
|
eventStore.getState().clearEvents();
|
||||||
productStore.getState().clearProducts();
|
productStore.getState().clearProducts();
|
||||||
materialStore.getState().clearMaterials();
|
materialStore.getState().clearMaterials();
|
||||||
@@ -92,7 +99,7 @@ export function SceneProvider({
|
|||||||
storageUnitStore.getState().clearStorageUnits();
|
storageUnitStore.getState().clearStorageUnits();
|
||||||
humanStore.getState().clearHumans();
|
humanStore.getState().clearHumans();
|
||||||
humanEventManagerRef.current.humanStates = [];
|
humanEventManagerRef.current.humanStates = [];
|
||||||
}, [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore]);
|
}, [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, undoRedo2DStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore]);
|
||||||
|
|
||||||
const contextValue = useMemo(() => (
|
const contextValue = useMemo(() => (
|
||||||
{
|
{
|
||||||
@@ -102,6 +109,7 @@ export function SceneProvider({
|
|||||||
aisleStore,
|
aisleStore,
|
||||||
zoneStore,
|
zoneStore,
|
||||||
floorStore,
|
floorStore,
|
||||||
|
undoRedo2DStore,
|
||||||
eventStore,
|
eventStore,
|
||||||
productStore,
|
productStore,
|
||||||
materialStore,
|
materialStore,
|
||||||
@@ -115,7 +123,7 @@ export function SceneProvider({
|
|||||||
clearStores,
|
clearStores,
|
||||||
layout
|
layout
|
||||||
}
|
}
|
||||||
), [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, clearStores, layout]);
|
), [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, undoRedo2DStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, clearStores, layout]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SceneContext.Provider value={contextValue}>
|
<SceneContext.Provider value={contextValue}>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ interface FloorStore {
|
|||||||
|
|
||||||
getFloorById: (uuid: string) => Floor | undefined;
|
getFloorById: (uuid: string) => Floor | undefined;
|
||||||
getFloorsByPointId: (uuid: string) => Floor[] | [];
|
getFloorsByPointId: (uuid: string) => Floor[] | [];
|
||||||
getFloorByPoints: (points: Point[]) => Floor | undefined;
|
getFloorsByPoints: (points: [Point, Point]) => Floor[] | [];
|
||||||
getFloorPointById: (uuid: string) => Point | undefined;
|
getFloorPointById: (uuid: string) => Point | undefined;
|
||||||
getConnectedPoints: (uuid: string) => Point[];
|
getConnectedPoints: (uuid: string) => Point[];
|
||||||
}
|
}
|
||||||
@@ -74,10 +74,13 @@ export const createFloorStore = () => {
|
|||||||
const updatedFloors: Floor[] = [];
|
const updatedFloors: Floor[] = [];
|
||||||
|
|
||||||
set(state => {
|
set(state => {
|
||||||
|
const newFloors: Floor[] = [];
|
||||||
|
|
||||||
for (const floor of state.floors) {
|
for (const floor of state.floors) {
|
||||||
const pointIndex = floor.points.findIndex(p => p.pointUuid === pointUuid);
|
const pointIndex = floor.points.findIndex(p => p.pointUuid === pointUuid);
|
||||||
|
|
||||||
if (pointIndex === -1) {
|
if (pointIndex === -1) {
|
||||||
updatedFloors.push(JSON.parse(JSON.stringify(floor)));
|
newFloors.push(floor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,11 +90,13 @@ export const createFloorStore = () => {
|
|||||||
removedFloors.push(JSON.parse(JSON.stringify(floor)));
|
removedFloors.push(JSON.parse(JSON.stringify(floor)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
floor.points = remainingPoints;
|
|
||||||
updatedFloors.push(JSON.parse(JSON.stringify(floor)));
|
const updatedFloor = { ...floor, points: remainingPoints };
|
||||||
|
updatedFloors.push(JSON.parse(JSON.stringify(updatedFloor)));
|
||||||
|
newFloors.push(updatedFloor);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.floors = updatedFloors;
|
state.floors = newFloors;
|
||||||
});
|
});
|
||||||
|
|
||||||
return { removedFloors, updatedFloors };
|
return { removedFloors, updatedFloors };
|
||||||
@@ -102,6 +107,7 @@ export const createFloorStore = () => {
|
|||||||
const updatedFloors: Floor[] = [];
|
const updatedFloors: Floor[] = [];
|
||||||
|
|
||||||
set(state => {
|
set(state => {
|
||||||
|
const newFloors: Floor[] = [];
|
||||||
|
|
||||||
for (const floor of state.floors) {
|
for (const floor of state.floors) {
|
||||||
const indices = floor.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
|
const indices = floor.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
|
||||||
@@ -110,7 +116,7 @@ export const createFloorStore = () => {
|
|||||||
const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
|
const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
|
||||||
|
|
||||||
if (idxA === -1 || idxB === -1) {
|
if (idxA === -1 || idxB === -1) {
|
||||||
updatedFloors.push(JSON.parse(JSON.stringify(floor)));
|
newFloors.push(floor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +126,7 @@ export const createFloorStore = () => {
|
|||||||
(idxB === 0 && idxA === floor.points.length - 1);
|
(idxB === 0 && idxA === floor.points.length - 1);
|
||||||
|
|
||||||
if (!areAdjacent) {
|
if (!areAdjacent) {
|
||||||
updatedFloors.push(JSON.parse(JSON.stringify(floor)));
|
newFloors.push(floor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,14 +135,15 @@ export const createFloorStore = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (remainingPoints.length > 2) {
|
if (remainingPoints.length > 2) {
|
||||||
floor.points = remainingPoints;
|
const updatedFloor = { ...floor, points: remainingPoints };
|
||||||
updatedFloors.push(JSON.parse(JSON.stringify(floor)));
|
updatedFloors.push(JSON.parse(JSON.stringify(updatedFloor)));
|
||||||
|
newFloors.push(updatedFloor);
|
||||||
} else {
|
} else {
|
||||||
removedFloors.push(JSON.parse(JSON.stringify(floor)));
|
removedFloors.push(JSON.parse(JSON.stringify(floor)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.floors = updatedFloors;
|
state.floors = newFloors;
|
||||||
});
|
});
|
||||||
|
|
||||||
return { removedFloors, updatedFloors };
|
return { removedFloors, updatedFloors };
|
||||||
@@ -253,12 +260,32 @@ export const createFloorStore = () => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getFloorByPoints: (points) => {
|
getFloorsByPoints: ([pointA, pointB]) => {
|
||||||
return get().floors.find(floor => {
|
const Floors: Floor[] = [];
|
||||||
const floorPointIds = new Set(floor.points.map(p => p.pointUuid));
|
|
||||||
const givenPointIds = new Set(points.map(p => p.pointUuid));
|
for (const floor of get().floors) {
|
||||||
return floorPointIds.size === givenPointIds.size && [...floorPointIds].every(id => givenPointIds.has(id));
|
const indices = floor.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
|
||||||
});
|
|
||||||
|
const idxA = indices.find(i => i.uuid === pointA.pointUuid)?.index ?? -1;
|
||||||
|
const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
|
||||||
|
|
||||||
|
if (idxA === -1 || idxB === -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const areAdjacent =
|
||||||
|
Math.abs(idxA - idxB) === 1 ||
|
||||||
|
(idxA === 0 && idxB === floor.points.length - 1) ||
|
||||||
|
(idxB === 0 && idxA === floor.points.length - 1);
|
||||||
|
|
||||||
|
if (!areAdjacent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Floors.push(JSON.parse(JSON.stringify(floor)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Floors;
|
||||||
},
|
},
|
||||||
|
|
||||||
getFloorPointById: (pointUuid) => {
|
getFloorPointById: (pointUuid) => {
|
||||||
|
|||||||
78
app/src/store/builder/useUndoRedo2DStore.ts
Normal file
78
app/src/store/builder/useUndoRedo2DStore.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
import { undoRedoConfig } from '../../types/world/worldConstants';
|
||||||
|
|
||||||
|
type UndoRedo2DStore = {
|
||||||
|
undoStack: UndoRedo2DTypes[];
|
||||||
|
redoStack: UndoRedo2DTypes[];
|
||||||
|
|
||||||
|
push2D: (entry: UndoRedo2DTypes) => void;
|
||||||
|
undo2D: () => UndoRedo2DTypes | undefined;
|
||||||
|
redo2D: () => UndoRedo2DTypes | undefined;
|
||||||
|
clearUndoRedo2D: () => void;
|
||||||
|
|
||||||
|
peekUndo2D: () => UndoRedo2DTypes | undefined;
|
||||||
|
peekRedo2D: () => UndoRedo2DTypes | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createUndoRedo2DStore = () => {
|
||||||
|
return create<UndoRedo2DStore>()(
|
||||||
|
immer((set, get) => ({
|
||||||
|
undoStack: [],
|
||||||
|
redoStack: [],
|
||||||
|
|
||||||
|
push2D: (entry) => {
|
||||||
|
set((state) => {
|
||||||
|
state.undoStack.push(entry);
|
||||||
|
|
||||||
|
if (state.undoStack.length > undoRedoConfig.undoRedoCount) {
|
||||||
|
state.undoStack.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
state.redoStack = [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
undo2D: () => {
|
||||||
|
let lastAction: UndoRedo2DTypes | undefined;
|
||||||
|
set((state) => {
|
||||||
|
lastAction = state.undoStack.pop();
|
||||||
|
if (lastAction) {
|
||||||
|
state.redoStack.unshift(lastAction);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return lastAction;
|
||||||
|
},
|
||||||
|
|
||||||
|
redo2D: () => {
|
||||||
|
let redoAction: UndoRedo2DTypes | undefined;
|
||||||
|
set((state) => {
|
||||||
|
redoAction = state.redoStack.shift();
|
||||||
|
if (redoAction) {
|
||||||
|
state.undoStack.push(redoAction);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return redoAction;
|
||||||
|
},
|
||||||
|
|
||||||
|
clearUndoRedo2D: () => {
|
||||||
|
set((state) => {
|
||||||
|
state.undoStack = [];
|
||||||
|
state.redoStack = [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
peekUndo2D: () => {
|
||||||
|
const stack = get().undoStack;
|
||||||
|
return stack.length > 0 ? stack[stack.length - 1] : undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
peekRedo2D: () => {
|
||||||
|
const stack = get().redoStack;
|
||||||
|
return stack.length > 0 ? stack[0] : undefined;
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UndoRedo2DStoreType = ReturnType<typeof createUndoRedo2DStore>;
|
||||||
@@ -21,7 +21,7 @@ interface ZoneStore {
|
|||||||
|
|
||||||
getZoneById: (uuid: string) => Zone | undefined;
|
getZoneById: (uuid: string) => Zone | undefined;
|
||||||
getZonesByPointId: (uuid: string) => Zone[] | [];
|
getZonesByPointId: (uuid: string) => Zone[] | [];
|
||||||
getZoneByPoints: (points: Point[]) => Zone | undefined;
|
getZonesByPoints: (points: Point[]) => Zone[] | [];
|
||||||
getZonePointById: (uuid: string) => Point | undefined;
|
getZonePointById: (uuid: string) => Point | undefined;
|
||||||
getConnectedPoints: (uuid: string) => Point[];
|
getConnectedPoints: (uuid: string) => Point[];
|
||||||
}
|
}
|
||||||
@@ -76,10 +76,13 @@ export const createZoneStore = () => {
|
|||||||
const updatedZones: Zone[] = [];
|
const updatedZones: Zone[] = [];
|
||||||
|
|
||||||
set(state => {
|
set(state => {
|
||||||
|
const newZones: Zone[] = [];
|
||||||
|
|
||||||
for (const zone of state.zones) {
|
for (const zone of state.zones) {
|
||||||
const pointIndex = zone.points.findIndex(p => p.pointUuid === pointUuid);
|
const pointIndex = zone.points.findIndex(p => p.pointUuid === pointUuid);
|
||||||
|
|
||||||
if (pointIndex === -1) {
|
if (pointIndex === -1) {
|
||||||
updatedZones.push(JSON.parse(JSON.stringify(zone)));
|
newZones.push(zone);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,11 +92,13 @@ export const createZoneStore = () => {
|
|||||||
removedZones.push(JSON.parse(JSON.stringify(zone)));
|
removedZones.push(JSON.parse(JSON.stringify(zone)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
zone.points = remainingPoints;
|
|
||||||
updatedZones.push(JSON.parse(JSON.stringify(zone)));
|
const updatedZone = { ...zone, points: remainingPoints };
|
||||||
|
updatedZones.push(JSON.parse(JSON.stringify(updatedZone)));
|
||||||
|
newZones.push(updatedZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.zones = updatedZones;
|
state.zones = newZones;
|
||||||
});
|
});
|
||||||
|
|
||||||
return { removedZones, updatedZones };
|
return { removedZones, updatedZones };
|
||||||
@@ -104,6 +109,7 @@ export const createZoneStore = () => {
|
|||||||
const updatedZones: Zone[] = [];
|
const updatedZones: Zone[] = [];
|
||||||
|
|
||||||
set(state => {
|
set(state => {
|
||||||
|
const newZones: Zone[] = [];
|
||||||
|
|
||||||
for (const zone of state.zones) {
|
for (const zone of state.zones) {
|
||||||
const indices = zone.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
|
const indices = zone.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
|
||||||
@@ -112,7 +118,7 @@ export const createZoneStore = () => {
|
|||||||
const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
|
const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
|
||||||
|
|
||||||
if (idxA === -1 || idxB === -1) {
|
if (idxA === -1 || idxB === -1) {
|
||||||
updatedZones.push(JSON.parse(JSON.stringify(zone)));
|
newZones.push(zone);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +128,7 @@ export const createZoneStore = () => {
|
|||||||
(idxB === 0 && idxA === zone.points.length - 1);
|
(idxB === 0 && idxA === zone.points.length - 1);
|
||||||
|
|
||||||
if (!areAdjacent) {
|
if (!areAdjacent) {
|
||||||
updatedZones.push(JSON.parse(JSON.stringify(zone)));
|
newZones.push(zone);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,14 +137,15 @@ export const createZoneStore = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (remainingPoints.length > 2) {
|
if (remainingPoints.length > 2) {
|
||||||
zone.points = remainingPoints;
|
const updatedZone = { ...zone, points: remainingPoints };
|
||||||
updatedZones.push(JSON.parse(JSON.stringify(zone)));
|
updatedZones.push(JSON.parse(JSON.stringify(updatedZone)));
|
||||||
|
newZones.push(updatedZone);
|
||||||
} else {
|
} else {
|
||||||
removedZones.push(JSON.parse(JSON.stringify(zone)));
|
removedZones.push(JSON.parse(JSON.stringify(zone)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.zones = updatedZones;
|
state.zones = newZones;
|
||||||
});
|
});
|
||||||
|
|
||||||
return { removedZones, updatedZones };
|
return { removedZones, updatedZones };
|
||||||
@@ -180,12 +187,32 @@ export const createZoneStore = () => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getZoneByPoints: (points) => {
|
getZonesByPoints: ([pointA, pointB]) => {
|
||||||
return get().zones.find(zone => {
|
const Zones: Zone[] = [];
|
||||||
const zonePointIds = new Set(zone.points.map(p => p.pointUuid));
|
|
||||||
const givenPointIds = new Set(points.map(p => p.pointUuid));
|
for (const zone of get().zones) {
|
||||||
return zonePointIds.size === givenPointIds.size && [...zonePointIds].every(id => givenPointIds.has(id));
|
const indices = zone.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
|
||||||
});
|
|
||||||
|
const idxA = indices.find(i => i.uuid === pointA.pointUuid)?.index ?? -1;
|
||||||
|
const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
|
||||||
|
|
||||||
|
if (idxA === -1 || idxB === -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const areAdjacent =
|
||||||
|
Math.abs(idxA - idxB) === 1 ||
|
||||||
|
(idxA === 0 && idxB === zone.points.length - 1) ||
|
||||||
|
(idxB === 0 && idxA === zone.points.length - 1);
|
||||||
|
|
||||||
|
if (!areAdjacent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Zones.push(JSON.parse(JSON.stringify(zone)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Zones;
|
||||||
},
|
},
|
||||||
|
|
||||||
getZonePointById: (pointUuid) => {
|
getZonePointById: (pointUuid) => {
|
||||||
|
|||||||
38
app/src/types/builderTypes.d.ts
vendored
38
app/src/types/builderTypes.d.ts
vendored
@@ -215,3 +215,41 @@ interface Aisle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Aisles = Aisle[];
|
type Aisles = Aisle[];
|
||||||
|
|
||||||
|
|
||||||
|
// Undo/Redo 2D
|
||||||
|
|
||||||
|
type UndoRedo2DDataTypeSchema =
|
||||||
|
| { type: 'Wall'; lineData: Wall; newData?: Wall; timeStamp: string }
|
||||||
|
| { type: 'Floor'; lineData: Floor; newData?: Floor; timeStamp: string }
|
||||||
|
| { type: 'Zone'; lineData: Zone; newData?: Zone; timeStamp: string }
|
||||||
|
| { type: 'Aisle'; lineData: Aisle; newData?: Aisle; timeStamp: string };
|
||||||
|
|
||||||
|
type UndoRedo2DLineActionSchema = {
|
||||||
|
actionType: 'Line-Create' | 'Line-Update' | 'Line-Delete';
|
||||||
|
point: UndoRedo2DDataTypeSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
type UndoRedo2DLinesActionSchema = {
|
||||||
|
actionType: 'Lines-Create' | 'Lines-Update' | 'Lines-Delete';
|
||||||
|
points: UndoRedo2DDataTypeSchema[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type UndoRedo2DAction = UndoRedo2DLineActionSchema | UndoRedo2DLinesActionSchema;
|
||||||
|
|
||||||
|
type UndoRedo2DDraw = {
|
||||||
|
type: 'Draw';
|
||||||
|
actions: UndoRedo2DAction[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type UndoRedo2DUi = {
|
||||||
|
type: 'UI';
|
||||||
|
action: any; // Define UI actions as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
type UndoRedo2DTypes = UndoRedo2DDraw | UndoRedo2DUi
|
||||||
|
|
||||||
|
type UndoRedo2D = {
|
||||||
|
undoStack: UndoRedo2DTypes[];
|
||||||
|
redoStack: UndoRedo2DTypes[];
|
||||||
|
};
|
||||||
@@ -1,375 +1,383 @@
|
|||||||
const savedTheme: string | null = localStorage.getItem("theme");
|
const savedTheme: string | null = localStorage.getItem("theme");
|
||||||
|
|
||||||
export type Controls = {
|
export type Controls = {
|
||||||
azimuthRotateSpeed: number;
|
azimuthRotateSpeed: number;
|
||||||
polarRotateSpeed: number;
|
polarRotateSpeed: number;
|
||||||
truckSpeed: number;
|
truckSpeed: number;
|
||||||
minDistance: number;
|
minDistance: number;
|
||||||
maxDistance: number;
|
maxDistance: number;
|
||||||
maxPolarAngle: number;
|
maxPolarAngle: number;
|
||||||
leftMouse: number;
|
leftMouse: number;
|
||||||
forwardSpeed: number;
|
forwardSpeed: number;
|
||||||
backwardSpeed: number;
|
backwardSpeed: number;
|
||||||
leftSpeed: number;
|
leftSpeed: number;
|
||||||
rightSpeed: number;
|
rightSpeed: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ThirdPersonControls = {
|
export type ThirdPersonControls = {
|
||||||
azimuthRotateSpeed: number;
|
azimuthRotateSpeed: number;
|
||||||
polarRotateSpeed: number;
|
polarRotateSpeed: number;
|
||||||
truckSpeed: number;
|
truckSpeed: number;
|
||||||
maxDistance: number;
|
maxDistance: number;
|
||||||
maxPolarAngle: number;
|
maxPolarAngle: number;
|
||||||
minZoom: number;
|
minZoom: number;
|
||||||
maxZoom: number;
|
maxZoom: number;
|
||||||
targetOffset: number;
|
targetOffset: number;
|
||||||
cameraHeight: number;
|
cameraHeight: number;
|
||||||
leftMouse: number;
|
leftMouse: number;
|
||||||
rightMouse: number;
|
rightMouse: number;
|
||||||
wheelMouse: number;
|
wheelMouse: number;
|
||||||
middleMouse: number;
|
middleMouse: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ControlsTransition = {
|
export type ControlsTransition = {
|
||||||
leftMouse: number;
|
leftMouse: number;
|
||||||
rightMouse: number;
|
rightMouse: number;
|
||||||
wheelMouse: number;
|
wheelMouse: number;
|
||||||
middleMouse: number;
|
middleMouse: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TwoDimension = {
|
export type TwoDimension = {
|
||||||
defaultPosition: [x: number, y: number, z: number];
|
defaultPosition: [x: number, y: number, z: number];
|
||||||
defaultTarget: [x: number, y: number, z: number];
|
defaultTarget: [x: number, y: number, z: number];
|
||||||
defaultAzimuth: number;
|
defaultAzimuth: number;
|
||||||
minDistance: number;
|
minDistance: number;
|
||||||
leftMouse: number;
|
leftMouse: number;
|
||||||
rightMouse: number;
|
rightMouse: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ThreeDimension = {
|
export type ThreeDimension = {
|
||||||
defaultPosition: [x: number, y: number, z: number];
|
defaultPosition: [x: number, y: number, z: number];
|
||||||
defaultTarget: [x: number, y: number, z: number];
|
defaultTarget: [x: number, y: number, z: number];
|
||||||
defaultRotation: [x: number, y: number, z: number];
|
defaultRotation: [x: number, y: number, z: number];
|
||||||
defaultAzimuth: number;
|
defaultAzimuth: number;
|
||||||
boundaryBottom: [x: number, y: number, z: number];
|
boundaryBottom: [x: number, y: number, z: number];
|
||||||
boundaryTop: [x: number, y: number, z: number];
|
boundaryTop: [x: number, y: number, z: number];
|
||||||
minDistance: number;
|
minDistance: number;
|
||||||
leftMouse: number;
|
leftMouse: number;
|
||||||
rightMouse: number;
|
rightMouse: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GridConfig = {
|
export type GridConfig = {
|
||||||
size: number;
|
size: number;
|
||||||
divisions: number;
|
divisions: number;
|
||||||
primaryColor: string;
|
primaryColor: string;
|
||||||
secondaryColor: string;
|
secondaryColor: string;
|
||||||
position2D: [x: number, y: number, z: number];
|
position2D: [x: number, y: number, z: number];
|
||||||
position3D: [x: number, y: number, z: number];
|
position3D: [x: number, y: number, z: number];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PlaneConfig = {
|
export type PlaneConfig = {
|
||||||
position2D: [x: number, y: number, z: number];
|
position2D: [x: number, y: number, z: number];
|
||||||
position3D: [x: number, y: number, z: number];
|
position3D: [x: number, y: number, z: number];
|
||||||
rotation: number;
|
rotation: number;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
color: string;
|
color: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ShadowConfig = {
|
export type ShadowConfig = {
|
||||||
shadowOffset: number;
|
shadowOffset: number;
|
||||||
shadowmapSizewidth: number;
|
shadowmapSizewidth: number;
|
||||||
shadowmapSizeheight: number;
|
shadowmapSizeheight: number;
|
||||||
shadowcamerafar: number;
|
shadowcamerafar: number;
|
||||||
shadowcameranear: number;
|
shadowcameranear: number;
|
||||||
shadowcameratop: number;
|
shadowcameratop: number;
|
||||||
shadowcamerabottom: number;
|
shadowcamerabottom: number;
|
||||||
shadowcameraleft: number;
|
shadowcameraleft: number;
|
||||||
shadowcameraright: number;
|
shadowcameraright: number;
|
||||||
shadowbias: number;
|
shadowbias: number;
|
||||||
shadownormalBias: number;
|
shadownormalBias: number;
|
||||||
shadowMaterialPosition: [x: number, y: number, z: number];
|
shadowMaterialPosition: [x: number, y: number, z: number];
|
||||||
shadowMaterialRotation: [x: number, y: number, z: number];
|
shadowMaterialRotation: [x: number, y: number, z: number];
|
||||||
shadowMaterialOpacity: number;
|
shadowMaterialOpacity: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SkyConfig = {
|
export type SkyConfig = {
|
||||||
defaultTurbidity: number;
|
defaultTurbidity: number;
|
||||||
maxTurbidity: number;
|
maxTurbidity: number;
|
||||||
minTurbidity: number;
|
minTurbidity: number;
|
||||||
defaultRayleigh: number;
|
defaultRayleigh: number;
|
||||||
mieCoefficient: number;
|
mieCoefficient: number;
|
||||||
mieDirectionalG: number;
|
mieDirectionalG: number;
|
||||||
skyDistance: number;
|
skyDistance: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AssetConfig = {
|
export type AssetConfig = {
|
||||||
defaultScaleBeforeGsap: [number, number, number];
|
defaultScaleBeforeGsap: [number, number, number];
|
||||||
defaultScaleAfterGsap: [number, number, number];
|
defaultScaleAfterGsap: [number, number, number];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PointConfig = {
|
export type PointConfig = {
|
||||||
defaultInnerColor: string;
|
defaultInnerColor: string;
|
||||||
defaultOuterColor: string;
|
defaultOuterColor: string;
|
||||||
deleteColor: string;
|
deleteColor: string;
|
||||||
boxScale: [number, number, number];
|
boxScale: [number, number, number];
|
||||||
wallOuterColor: string;
|
wallOuterColor: string;
|
||||||
floorOuterColor: string;
|
floorOuterColor: string;
|
||||||
aisleOuterColor: string;
|
aisleOuterColor: string;
|
||||||
zoneOuterColor: string;
|
zoneOuterColor: string;
|
||||||
snappingThreshold: number;
|
snappingThreshold: number;
|
||||||
helperColor: string;
|
helperColor: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LineConfig = {
|
export type LineConfig = {
|
||||||
tubularSegments: number;
|
tubularSegments: number;
|
||||||
radius: number;
|
radius: number;
|
||||||
radialSegments: number;
|
radialSegments: number;
|
||||||
wallName: string;
|
wallName: string;
|
||||||
floorName: string;
|
floorName: string;
|
||||||
aisleName: string;
|
aisleName: string;
|
||||||
zoneName: string;
|
zoneName: string;
|
||||||
referenceName: string;
|
referenceName: string;
|
||||||
lineIntersectionPoints: number;
|
lineIntersectionPoints: number;
|
||||||
defaultColor: string;
|
defaultColor: string;
|
||||||
wallColor: string;
|
wallColor: string;
|
||||||
floorColor: string;
|
floorColor: string;
|
||||||
aisleColor: string;
|
aisleColor: string;
|
||||||
zoneColor: string;
|
zoneColor: string;
|
||||||
deleteColor: string;
|
deleteColor: string;
|
||||||
helperColor: string;
|
helperColor: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WallConfig = {
|
export type WallConfig = {
|
||||||
defaultColor: string;
|
defaultColor: string;
|
||||||
height: number;
|
height: number;
|
||||||
width: number;
|
width: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FloorConfig = {
|
export type FloorConfig = {
|
||||||
defaultColor: string;
|
defaultColor: string;
|
||||||
height: number;
|
height: number;
|
||||||
textureScale: number;
|
textureScale: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RoofConfig = {
|
export type RoofConfig = {
|
||||||
defaultColor: string;
|
defaultColor: string;
|
||||||
height: number;
|
height: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AisleConfig = {
|
export type AisleConfig = {
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
defaultColor: string;
|
defaultColor: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ZoneConfig = {
|
export type ZoneConfig = {
|
||||||
defaultColor: string;
|
defaultColor: string;
|
||||||
height: number;
|
height: number;
|
||||||
color: string;
|
color: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ColumnConfig = {
|
export type ColumnConfig = {
|
||||||
defaultColor: string;
|
defaultColor: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type OutlineConfig = {
|
export type OutlineConfig = {
|
||||||
assetSelectColor: number;
|
assetSelectColor: number;
|
||||||
assetDeleteColor: number;
|
assetDeleteColor: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DistanceConfig = {
|
export type DistanceConfig = {
|
||||||
minDistance: number;
|
minDistance: number;
|
||||||
maxDistance: number;
|
maxDistance: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type undoRedoCount = {
|
||||||
|
undoRedoCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const firstPersonControls: Controls = {
|
export const firstPersonControls: Controls = {
|
||||||
azimuthRotateSpeed: 0.3, // Speed of rotation around the azimuth axis
|
azimuthRotateSpeed: 0.3, // Speed of rotation around the azimuth axis
|
||||||
polarRotateSpeed: 0.3, // Speed of rotation around the polar axis
|
polarRotateSpeed: 0.3, // Speed of rotation around the polar axis
|
||||||
truckSpeed: 10, // Speed of truck movement
|
truckSpeed: 10, // Speed of truck movement
|
||||||
minDistance: 0, // Minimum distance from the target
|
minDistance: 0, // Minimum distance from the target
|
||||||
maxDistance: 0, // Maximum distance from the target
|
maxDistance: 0, // Maximum distance from the target
|
||||||
maxPolarAngle: Math.PI, // Maximum polar angle
|
maxPolarAngle: Math.PI, // Maximum polar angle
|
||||||
leftMouse: 1, // Mouse button for rotation (ROTATE)
|
leftMouse: 1, // Mouse button for rotation (ROTATE)
|
||||||
forwardSpeed: 0.1, // Speed of forward movement
|
forwardSpeed: 0.1, // Speed of forward movement
|
||||||
backwardSpeed: -0.1, // Speed of backward movement
|
backwardSpeed: -0.1, // Speed of backward movement
|
||||||
leftSpeed: -0.1, // Speed of left movement
|
leftSpeed: -0.1, // Speed of left movement
|
||||||
rightSpeed: 0.1, // Speed of right movement
|
rightSpeed: 0.1, // Speed of right movement
|
||||||
};
|
};
|
||||||
|
|
||||||
export const thirdPersonControls: ThirdPersonControls = {
|
export const thirdPersonControls: ThirdPersonControls = {
|
||||||
azimuthRotateSpeed: 1, // Speed of rotation around the azimuth axis
|
azimuthRotateSpeed: 1, // Speed of rotation around the azimuth axis
|
||||||
polarRotateSpeed: 1, // Speed of rotation around the polar axis
|
polarRotateSpeed: 1, // Speed of rotation around the polar axis
|
||||||
truckSpeed: 2, // Speed of truck movement
|
truckSpeed: 2, // Speed of truck movement
|
||||||
maxDistance: 100, // Maximum distance from the target
|
maxDistance: 100, // Maximum distance from the target
|
||||||
maxPolarAngle: Math.PI / 2 - 0.05, // Maximum polar angle
|
maxPolarAngle: Math.PI / 2 - 0.05, // Maximum polar angle
|
||||||
minZoom: 6, // Minimum zoom level
|
minZoom: 6, // Minimum zoom level
|
||||||
maxZoom: 100, // Maximum zoom level
|
maxZoom: 100, // Maximum zoom level
|
||||||
targetOffset: 20, // Offset of the target from the camera
|
targetOffset: 20, // Offset of the target from the camera
|
||||||
cameraHeight: 30, // Height of the camera
|
cameraHeight: 30, // Height of the camera
|
||||||
leftMouse: 2, // Mouse button for panning
|
leftMouse: 2, // Mouse button for panning
|
||||||
rightMouse: 1, // Mouse button for rotation
|
rightMouse: 1, // Mouse button for rotation
|
||||||
wheelMouse: 8, // Mouse button for zooming
|
wheelMouse: 8, // Mouse button for zooming
|
||||||
middleMouse: 8, // Mouse button for zooming
|
middleMouse: 8, // Mouse button for zooming
|
||||||
};
|
};
|
||||||
|
|
||||||
export const controlsTransition: ControlsTransition = {
|
export const controlsTransition: ControlsTransition = {
|
||||||
leftMouse: 0, // Mouse button for no action
|
leftMouse: 0, // Mouse button for no action
|
||||||
rightMouse: 0, // Mouse button for no action
|
rightMouse: 0, // Mouse button for no action
|
||||||
wheelMouse: 0, // Mouse button for no action
|
wheelMouse: 0, // Mouse button for no action
|
||||||
middleMouse: 0, // Mouse button for no action
|
middleMouse: 0, // Mouse button for no action
|
||||||
};
|
};
|
||||||
|
|
||||||
export const twoDimension: TwoDimension = {
|
export const twoDimension: TwoDimension = {
|
||||||
defaultPosition: [0, 100, 0], // Default position of the camera
|
defaultPosition: [0, 100, 0], // Default position of the camera
|
||||||
defaultTarget: [0, 0, 0], // Default target of the camera
|
defaultTarget: [0, 0, 0], // Default target of the camera
|
||||||
defaultAzimuth: 0, // Default azimuth of the camera
|
defaultAzimuth: 0, // Default azimuth of the camera
|
||||||
minDistance: 25, // Minimum distance from the target
|
minDistance: 25, // Minimum distance from the target
|
||||||
leftMouse: 2, // Mouse button for panning
|
leftMouse: 2, // Mouse button for panning
|
||||||
rightMouse: 0, // Mouse button for no action
|
rightMouse: 0, // Mouse button for no action
|
||||||
};
|
};
|
||||||
|
|
||||||
export const camPositionUpdateInterval: number = 200; // Interval for updating the camera position
|
export const camPositionUpdateInterval: number = 200; // Interval for updating the camera position
|
||||||
|
|
||||||
export const gridConfig: GridConfig = {
|
export const gridConfig: GridConfig = {
|
||||||
size: 150, // Size of the grid
|
size: 150, // Size of the grid
|
||||||
divisions: 75, // Number of divisions in the grid
|
divisions: 75, // Number of divisions in the grid
|
||||||
primaryColor: savedTheme === "dark" ? "#131313" : "#d5d5d5", // Primary color of the grid
|
primaryColor: savedTheme === "dark" ? "#131313" : "#d5d5d5", // Primary color of the grid
|
||||||
secondaryColor: savedTheme === "dark" ? "#434343" : "#e3e3e3", // Secondary color of the grid
|
secondaryColor: savedTheme === "dark" ? "#434343" : "#e3e3e3", // Secondary color of the grid
|
||||||
|
|
||||||
position2D: [0, 0.1, 0], // Position of the grid in 2D view
|
position2D: [0, 0.1, 0], // Position of the grid in 2D view
|
||||||
position3D: [0, -0.5, 0], // Position of the grid in 3D view
|
position3D: [0, -0.5, 0], // Position of the grid in 3D view
|
||||||
};
|
};
|
||||||
|
|
||||||
export const threeDimension: ThreeDimension = {
|
export const threeDimension: ThreeDimension = {
|
||||||
defaultPosition: [0, 40, 30], // Default position of the camera
|
defaultPosition: [0, 40, 30], // Default position of the camera
|
||||||
defaultTarget: [0, 0, 0], // Default target of the camera
|
defaultTarget: [0, 0, 0], // Default target of the camera
|
||||||
defaultRotation: [0, 0, 0], // Default rotation of the camera
|
defaultRotation: [0, 0, 0], // Default rotation of the camera
|
||||||
defaultAzimuth: 0, // Default azimuth of the camera
|
defaultAzimuth: 0, // Default azimuth of the camera
|
||||||
boundaryBottom: [-gridConfig.size / 2, 0, -gridConfig.size / 2], // Bottom boundary of the camera movement
|
boundaryBottom: [-gridConfig.size / 2, 0, -gridConfig.size / 2], // Bottom boundary of the camera movement
|
||||||
boundaryTop: [gridConfig.size / 2, 100, gridConfig.size / 2], // Top boundary of the camera movement
|
boundaryTop: [gridConfig.size / 2, 100, gridConfig.size / 2], // Top boundary of the camera movement
|
||||||
minDistance: 1, // Minimum distance from the target
|
minDistance: 1, // Minimum distance from the target
|
||||||
leftMouse: 2, // Mouse button for panning
|
leftMouse: 2, // Mouse button for panning
|
||||||
rightMouse: 1, // Mouse button for rotation
|
rightMouse: 1, // Mouse button for rotation
|
||||||
};
|
};
|
||||||
|
|
||||||
export const planeConfig: PlaneConfig = {
|
export const planeConfig: PlaneConfig = {
|
||||||
position2D: [0, -0.5, 0], // Position of the plane
|
position2D: [0, -0.5, 0], // Position of the plane
|
||||||
position3D: [0, -0.65, 0], // Position of the plane
|
position3D: [0, -0.65, 0], // Position of the plane
|
||||||
rotation: -Math.PI / 2, // Rotation of the plane
|
rotation: -Math.PI / 2, // Rotation of the plane
|
||||||
|
|
||||||
width: 150, // Width of the plane
|
width: 150, // Width of the plane
|
||||||
height: 150, // Height of the plane
|
height: 150, // Height of the plane
|
||||||
color: savedTheme === "dark" ? "#323232" : "#f3f3f3", // Color of the plane
|
color: savedTheme === "dark" ? "#323232" : "#f3f3f3", // Color of the plane
|
||||||
};
|
};
|
||||||
|
|
||||||
export const shadowConfig: ShadowConfig = {
|
export const shadowConfig: ShadowConfig = {
|
||||||
shadowOffset: 50, // Offset of the shadow
|
shadowOffset: 50, // Offset of the shadow
|
||||||
// shadowmapSizewidth: 1024, // Width of the shadow map
|
// shadowmapSizewidth: 1024, // Width of the shadow map
|
||||||
// shadowmapSizeheight: 1024, // Height of the shadow map
|
// shadowmapSizeheight: 1024, // Height of the shadow map
|
||||||
shadowmapSizewidth: 2048, // Width of the shadow map
|
shadowmapSizewidth: 2048, // Width of the shadow map
|
||||||
shadowmapSizeheight: 2048, // Height of the shadow map
|
shadowmapSizeheight: 2048, // Height of the shadow map
|
||||||
// shadowmapSizewidth: 8192, // Width of the shadow map
|
// shadowmapSizewidth: 8192, // Width of the shadow map
|
||||||
// shadowmapSizeheight: 8192, // Height of the shadow map
|
// shadowmapSizeheight: 8192, // Height of the shadow map
|
||||||
shadowcamerafar: 70, // Far plane of the shadow camera
|
shadowcamerafar: 70, // Far plane of the shadow camera
|
||||||
shadowcameranear: 0.1, // Near plane of the shadow camera
|
shadowcameranear: 0.1, // Near plane of the shadow camera
|
||||||
shadowcameratop: 30, // Top plane of the shadow camera
|
shadowcameratop: 30, // Top plane of the shadow camera
|
||||||
shadowcamerabottom: -30, // Bottom plane of the shadow camera
|
shadowcamerabottom: -30, // Bottom plane of the shadow camera
|
||||||
shadowcameraleft: -30, // Left plane of the shadow camera
|
shadowcameraleft: -30, // Left plane of the shadow camera
|
||||||
shadowcameraright: 30, // Right plane of the shadow camera
|
shadowcameraright: 30, // Right plane of the shadow camera
|
||||||
shadowbias: -0.001, // Bias of the shadow
|
shadowbias: -0.001, // Bias of the shadow
|
||||||
shadownormalBias: 0.02, // Normal bias of the shadow
|
shadownormalBias: 0.02, // Normal bias of the shadow
|
||||||
shadowMaterialPosition: [0, 0.01, 0], // Position of the shadow material
|
shadowMaterialPosition: [0, 0.01, 0], // Position of the shadow material
|
||||||
shadowMaterialRotation: [-Math.PI / 2, 0, 0], // Rotation of the shadow material
|
shadowMaterialRotation: [-Math.PI / 2, 0, 0], // Rotation of the shadow material
|
||||||
shadowMaterialOpacity: 0.1, // Opacity of the shadow material
|
shadowMaterialOpacity: 0.1, // Opacity of the shadow material
|
||||||
};
|
};
|
||||||
|
|
||||||
export const skyConfig: SkyConfig = {
|
export const skyConfig: SkyConfig = {
|
||||||
defaultTurbidity: 10.0, // Default turbidity of the sky
|
defaultTurbidity: 10.0, // Default turbidity of the sky
|
||||||
maxTurbidity: 20.0, // Maximum turbidity of the sky
|
maxTurbidity: 20.0, // Maximum turbidity of the sky
|
||||||
minTurbidity: 0.0, // Minimum turbidity of the sky
|
minTurbidity: 0.0, // Minimum turbidity of the sky
|
||||||
defaultRayleigh: 1.9, // Default Rayleigh scattering coefficient
|
defaultRayleigh: 1.9, // Default Rayleigh scattering coefficient
|
||||||
mieCoefficient: 0.1, // Mie scattering coefficient
|
mieCoefficient: 0.1, // Mie scattering coefficient
|
||||||
mieDirectionalG: 1.0, // Mie directional G
|
mieDirectionalG: 1.0, // Mie directional G
|
||||||
skyDistance: 2000, // Distance of the sky
|
skyDistance: 2000, // Distance of the sky
|
||||||
};
|
};
|
||||||
|
|
||||||
export const assetConfig: AssetConfig = {
|
export const assetConfig: AssetConfig = {
|
||||||
defaultScaleBeforeGsap: [0.1, 0.1, 0.1], // Default scale of the assets
|
defaultScaleBeforeGsap: [0.1, 0.1, 0.1], // Default scale of the assets
|
||||||
defaultScaleAfterGsap: [1, 1, 1], // Default scale of the assets
|
defaultScaleAfterGsap: [1, 1, 1], // Default scale of the assets
|
||||||
};
|
};
|
||||||
|
|
||||||
export const pointConfig: PointConfig = {
|
export const pointConfig: PointConfig = {
|
||||||
defaultInnerColor: "#ffffff", // Default inner color of the points
|
defaultInnerColor: "#ffffff", // Default inner color of the points
|
||||||
defaultOuterColor: "#ffffff", // Default outer color of the points
|
defaultOuterColor: "#ffffff", // Default outer color of the points
|
||||||
deleteColor: "#ff0000", // Color of the points when deleting
|
deleteColor: "#ff0000", // Color of the points when deleting
|
||||||
boxScale: [0.5, 0.5, 0.5], // Scale of the points
|
boxScale: [0.5, 0.5, 0.5], // Scale of the points
|
||||||
wallOuterColor: "#C7C7C7", // Outer color of the wall points
|
wallOuterColor: "#C7C7C7", // Outer color of the wall points
|
||||||
floorOuterColor: "#808080", // Outer color of the floor points
|
floorOuterColor: "#808080", // Outer color of the floor points
|
||||||
aisleOuterColor: "#FBBC05", // Outer color of the aisle points
|
aisleOuterColor: "#FBBC05", // Outer color of the aisle points
|
||||||
zoneOuterColor: "#007BFF", // Outer color of the zone points
|
zoneOuterColor: "#007BFF", // Outer color of the zone points
|
||||||
snappingThreshold: 1, // Threshold for snapping
|
snappingThreshold: 1, // Threshold for snapping
|
||||||
helperColor: "#C164FF", // Color of the helper lines
|
helperColor: "#C164FF", // Color of the helper lines
|
||||||
};
|
};
|
||||||
|
|
||||||
export const lineConfig: LineConfig = {
|
export const lineConfig: LineConfig = {
|
||||||
tubularSegments: 64, // Number of tubular segments
|
tubularSegments: 64, // Number of tubular segments
|
||||||
radius: 0.15, // Radius of the lines
|
radius: 0.15, // Radius of the lines
|
||||||
radialSegments: 8, // Number of radial segments
|
radialSegments: 8, // Number of radial segments
|
||||||
wallName: "WallLine", // Name of the wall lines
|
wallName: "WallLine", // Name of the wall lines
|
||||||
floorName: "FloorLine", // Name of the floor lines
|
floorName: "FloorLine", // Name of the floor lines
|
||||||
aisleName: "AisleLine", // Name of the aisle lines
|
aisleName: "AisleLine", // Name of the aisle lines
|
||||||
zoneName: "ZoneLine", // Name of the zone lines
|
zoneName: "ZoneLine", // Name of the zone lines
|
||||||
referenceName: "ReferenceLine", // Name of the reference lines
|
referenceName: "ReferenceLine", // Name of the reference lines
|
||||||
lineIntersectionPoints: 300, // Number of intersection points
|
lineIntersectionPoints: 300, // Number of intersection points
|
||||||
defaultColor: "#000000", // Default color of the lines
|
defaultColor: "#000000", // Default color of the lines
|
||||||
wallColor: "#C7C7C7", // Color of the wall lines
|
wallColor: "#C7C7C7", // Color of the wall lines
|
||||||
floorColor: "#808080", // Color of the floor lines
|
floorColor: "#808080", // Color of the floor lines
|
||||||
aisleColor: "#FBBC05", // Color of the aisle lines
|
aisleColor: "#FBBC05", // Color of the aisle lines
|
||||||
zoneColor: "#007BFF", // Color of the zone lines
|
zoneColor: "#007BFF", // Color of the zone lines
|
||||||
deleteColor: "#ff0000", // Color of the line when deleting
|
deleteColor: "#ff0000", // Color of the line when deleting
|
||||||
helperColor: "#C164FF", // Color of the helper lines
|
helperColor: "#C164FF", // Color of the helper lines
|
||||||
};
|
};
|
||||||
|
|
||||||
export const wallConfig: WallConfig = {
|
export const wallConfig: WallConfig = {
|
||||||
defaultColor: "#f2f2f2", // Default color of the walls
|
defaultColor: "#f2f2f2", // Default color of the walls
|
||||||
height: 7.5, // Height of the walls
|
height: 7.5, // Height of the walls
|
||||||
width: 0.05, // Width of the walls
|
width: 0.05, // Width of the walls
|
||||||
};
|
};
|
||||||
|
|
||||||
export const floorConfig: FloorConfig = {
|
export const floorConfig: FloorConfig = {
|
||||||
defaultColor: "grey", // Default color of the floors
|
defaultColor: "grey", // Default color of the floors
|
||||||
height: 0.1, // Height of the floors
|
height: 0.1, // Height of the floors
|
||||||
textureScale: 1, // Scale of the floor texture
|
textureScale: 1, // Scale of the floor texture
|
||||||
};
|
};
|
||||||
|
|
||||||
export const roofConfig: RoofConfig = {
|
export const roofConfig: RoofConfig = {
|
||||||
defaultColor: "grey", // Default color of the roofs
|
defaultColor: "grey", // Default color of the roofs
|
||||||
height: 0.1, // Height of the roofs
|
height: 0.1, // Height of the roofs
|
||||||
};
|
};
|
||||||
|
|
||||||
export const aisleConfig: AisleConfig = {
|
export const aisleConfig: AisleConfig = {
|
||||||
width: 0.1, // Width of the aisles
|
width: 0.1, // Width of the aisles
|
||||||
height: 0.01, // Height of the aisles
|
height: 0.01, // Height of the aisles
|
||||||
defaultColor: '#E2AC09', // Default color of the aisles
|
defaultColor: '#E2AC09', // Default color of the aisles
|
||||||
};
|
};
|
||||||
|
|
||||||
export const zoneConfig: ZoneConfig = {
|
export const zoneConfig: ZoneConfig = {
|
||||||
defaultColor: "black", // Default color of the zones
|
defaultColor: "black", // Default color of the zones
|
||||||
height: 3,
|
height: 3,
|
||||||
color: "#8656DF", // Color of the zones
|
color: "#8656DF", // Color of the zones
|
||||||
};
|
};
|
||||||
|
|
||||||
export const columnConfig: ColumnConfig = {
|
export const columnConfig: ColumnConfig = {
|
||||||
defaultColor: "White", // Default color of the columns
|
defaultColor: "White", // Default color of the columns
|
||||||
};
|
};
|
||||||
|
|
||||||
export const outlineConfig: OutlineConfig = {
|
export const outlineConfig: OutlineConfig = {
|
||||||
assetSelectColor: 0x0054fe, // Color of the selected assets
|
assetSelectColor: 0x0054fe, // Color of the selected assets
|
||||||
assetDeleteColor: 0xff0000, // Color of the deleted assets
|
assetDeleteColor: 0xff0000, // Color of the deleted assets
|
||||||
};
|
};
|
||||||
|
|
||||||
export const distanceConfig: DistanceConfig = {
|
export const distanceConfig: DistanceConfig = {
|
||||||
minDistance: 20,
|
minDistance: 20,
|
||||||
maxDistance: 75,
|
maxDistance: 75,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const undoRedoConfig: undoRedoCount = {
|
||||||
|
undoRedoCount: 50,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user