Refactor success notifications to use echo instead of toast; update selection controls and duplication logic
- Changed success notifications from `toast.success` to `echo.success` in copy, duplication, move, rotate, and selection controls. - Updated selection logic in `PostProcessing` to use `flattenChildren` for better performance. - Enhanced `Simulator` component to handle selected product state and execution order more effectively. - Modified `useSelectedItem` state to include `category` and `subCategory` properties for better item classification. - Adjusted `WallItem` interface to standardize type values and added `modelfileID` for improved asset management.
This commit is contained in:
@@ -140,16 +140,14 @@ const Assets: React.FC = () => {
|
|||||||
alt={asset.filename}
|
alt={asset.filename}
|
||||||
className="asset-image"
|
className="asset-image"
|
||||||
onPointerDown={() => {
|
onPointerDown={() => {
|
||||||
if (asset.category !== 'Feneration') {
|
setSelectedItem({
|
||||||
setSelectedItem({
|
name: asset.filename,
|
||||||
name: asset.filename,
|
id: asset.AssetID,
|
||||||
id: asset.AssetID,
|
type:
|
||||||
type:
|
asset.type === "undefined"
|
||||||
asset.type === "undefined"
|
? undefined
|
||||||
? undefined
|
: asset.type
|
||||||
: asset.type,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -206,6 +204,8 @@ const Assets: React.FC = () => {
|
|||||||
asset.type === "undefined"
|
asset.type === "undefined"
|
||||||
? undefined
|
? undefined
|
||||||
: asset.type,
|
: asset.type,
|
||||||
|
category: asset.category,
|
||||||
|
subCategory: asset.subCategory
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ async function loadInitialFloorItems(
|
|||||||
// Check Three.js Cache
|
// Check Three.js Cache
|
||||||
const cachedModel = THREE.Cache.get(item.modelfileID!);
|
const cachedModel = THREE.Cache.get(item.modelfileID!);
|
||||||
if (cachedModel) {
|
if (cachedModel) {
|
||||||
//
|
|
||||||
processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems, addEvent);
|
processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems, addEvent);
|
||||||
modelsLoaded++;
|
modelsLoaded++;
|
||||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||||
@@ -81,7 +80,6 @@ async function loadInitialFloorItems(
|
|||||||
// Check IndexedDB
|
// Check IndexedDB
|
||||||
const indexedDBModel = await retrieveGLTF(item.modelfileID!);
|
const indexedDBModel = await retrieveGLTF(item.modelfileID!);
|
||||||
if (indexedDBModel) {
|
if (indexedDBModel) {
|
||||||
//
|
|
||||||
const blobUrl = URL.createObjectURL(indexedDBModel);
|
const blobUrl = URL.createObjectURL(indexedDBModel);
|
||||||
loader.load(blobUrl, (gltf) => {
|
loader.load(blobUrl, (gltf) => {
|
||||||
URL.revokeObjectURL(blobUrl);
|
URL.revokeObjectURL(blobUrl);
|
||||||
@@ -102,7 +100,6 @@ async function loadInitialFloorItems(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fetch from Backend
|
// Fetch from Backend
|
||||||
//
|
|
||||||
const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${item.modelfileID!}`;
|
const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${item.modelfileID!}`;
|
||||||
loader.load(modelUrl, async (gltf) => {
|
loader.load(modelUrl, async (gltf) => {
|
||||||
const modelBlob = await fetch(modelUrl).then((res) => res.blob());
|
const modelBlob = await fetch(modelUrl).then((res) => res.blob());
|
||||||
@@ -338,7 +335,7 @@ function checkLoadingCompletion(
|
|||||||
resolve: () => void
|
resolve: () => void
|
||||||
) {
|
) {
|
||||||
if (modelsLoaded === modelsToLoad) {
|
if (modelsLoaded === modelsToLoad) {
|
||||||
toast.success("Models Loaded!");
|
echo.success("Models Loaded!");
|
||||||
dracoLoader.dispose();
|
dracoLoader.dispose();
|
||||||
}
|
}
|
||||||
resolve();
|
resolve();
|
||||||
|
|||||||
@@ -1,54 +1,102 @@
|
|||||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||||
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
|
||||||
|
import * as THREE from 'three';
|
||||||
import * as Types from "../../../types/world/worldTypes";
|
import * as Types from "../../../types/world/worldTypes";
|
||||||
import { getWallItems } from '../../../services/factoryBuilder/assest/wallAsset/getWallItemsApi';
|
import { getWallItems } from '../../../services/factoryBuilder/assest/wallAsset/getWallItemsApi';
|
||||||
|
import { retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils';
|
||||||
////////// Load the Wall Items's intially of there is any //////////
|
|
||||||
|
|
||||||
async function loadInitialWallItems(
|
async function loadInitialWallItems(
|
||||||
setWallItems: Types.setWallItemSetState,
|
setWallItems: Types.setWallItemSetState,
|
||||||
AssetConfigurations: Types.AssetConfigurations
|
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
const email = localStorage.getItem('email');
|
||||||
|
if (!email) {
|
||||||
|
throw new Error('No email found in localStorage');
|
||||||
|
}
|
||||||
|
|
||||||
const email = localStorage.getItem('email')
|
const organization = email.split("@")[1].split(".")[0];
|
||||||
const organization = (email!.split("@")[1]).split(".")[0];
|
const items = await getWallItems(organization);
|
||||||
|
|
||||||
const items = await getWallItems(organization);
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||||
|
|
||||||
localStorage.setItem("WallItems", JSON.stringify(items));
|
if (!items || items.length === 0) {
|
||||||
if (items.length > 0) {
|
localStorage.removeItem("WallItems");
|
||||||
const storedWallItems: Types.wallItems = items;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const loadedWallItems = await Promise.all(storedWallItems.map(async (item) => {
|
localStorage.setItem("WallItems", JSON.stringify(items));
|
||||||
const loader = new GLTFLoader();
|
|
||||||
|
const loader = new GLTFLoader();
|
||||||
|
const dracoLoader = new DRACOLoader();
|
||||||
|
dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
|
||||||
|
loader.setDRACOLoader(dracoLoader);
|
||||||
|
|
||||||
|
const loadedWallItems = await Promise.all(items.map(async (item: Types.WallItem) => {
|
||||||
|
// Check THREE.js cache first
|
||||||
|
const cachedModel = THREE.Cache.get(item.modelName!);
|
||||||
|
if (cachedModel) {
|
||||||
|
return processModel(cachedModel, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check IndexedDB cache
|
||||||
|
const cachedModelBlob = await retrieveGLTF(item.modelfileID!);
|
||||||
|
if (cachedModelBlob) {
|
||||||
|
const blobUrl = URL.createObjectURL(cachedModelBlob);
|
||||||
|
return new Promise<Types.WallItem>((resolve) => {
|
||||||
|
loader.load(blobUrl, (gltf) => {
|
||||||
|
URL.revokeObjectURL(blobUrl);
|
||||||
|
THREE.Cache.add(item.modelName!, gltf);
|
||||||
|
resolve(processModel(gltf, item));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load from original URL if not cached
|
||||||
|
const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${item.modelfileID!}`;
|
||||||
return new Promise<Types.WallItem>((resolve) => {
|
return new Promise<Types.WallItem>((resolve) => {
|
||||||
loader.load(AssetConfigurations[item.modelName!].modelUrl, (gltf) => {
|
loader.load(modelUrl, async (gltf) => {
|
||||||
const model = gltf.scene;
|
try {
|
||||||
model.uuid = item.modelUuid!;
|
// Cache the model
|
||||||
|
const modelBlob = await fetch(modelUrl).then((res) => res.blob());
|
||||||
model.children[0].children.forEach((child: any) => {
|
await storeGLTF(item.modelName!, modelBlob);
|
||||||
if (child.name !== "CSG_REF") {
|
THREE.Cache.add(item.modelName!, gltf);
|
||||||
child.castShadow = true;
|
resolve(processModel(gltf, item));
|
||||||
child.receiveShadow = true;
|
} catch (error) {
|
||||||
}
|
console.error('Failed to cache model:', error);
|
||||||
|
resolve(processModel(gltf, item));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
resolve({
|
|
||||||
type: item.type,
|
|
||||||
model: model,
|
|
||||||
modelName: item.modelName,
|
|
||||||
scale: item.scale,
|
|
||||||
csgscale: item.csgscale,
|
|
||||||
csgposition: item.csgposition,
|
|
||||||
position: item.position,
|
|
||||||
quaternion: item.quaternion,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setWallItems(loadedWallItems);
|
setWallItems(loadedWallItems);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load wall items:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default loadInitialWallItems;
|
function processModel(gltf: GLTF, item: Types.WallItem): Types.WallItem {
|
||||||
|
const model = gltf.scene.clone();
|
||||||
|
model.uuid = item.modelUuid!;
|
||||||
|
|
||||||
|
model.children[0]?.children?.forEach((child: THREE.Object3D) => {
|
||||||
|
if (child.name !== "CSG_REF") {
|
||||||
|
child.castShadow = true;
|
||||||
|
child.receiveShadow = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: item.type,
|
||||||
|
model: model,
|
||||||
|
modelName: item.modelName,
|
||||||
|
modelfileID: item.modelfileID,
|
||||||
|
scale: item.scale,
|
||||||
|
csgscale: item.csgscale,
|
||||||
|
csgposition: item.csgposition,
|
||||||
|
position: item.position,
|
||||||
|
quaternion: item.quaternion,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default loadInitialWallItems;
|
||||||
@@ -126,32 +126,6 @@ export default function Builder() {
|
|||||||
// dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
|
// dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
|
||||||
// loader.setDRACOLoader(dracoLoader);
|
// loader.setDRACOLoader(dracoLoader);
|
||||||
|
|
||||||
////////// Assest Configuration Values //////////
|
|
||||||
|
|
||||||
const AssetConfigurations: Types.AssetConfigurations = {
|
|
||||||
arch: {
|
|
||||||
modelUrl: arch,
|
|
||||||
scale: [0.75, 0.75, 0.75],
|
|
||||||
csgscale: [2, 4, 0.5],
|
|
||||||
csgposition: [0, 2, 0],
|
|
||||||
type: "Fixed-Move",
|
|
||||||
},
|
|
||||||
door: {
|
|
||||||
modelUrl: door,
|
|
||||||
scale: [0.75, 0.75, 0.75],
|
|
||||||
csgscale: [2, 4, 0.5],
|
|
||||||
csgposition: [0, 2, 0],
|
|
||||||
type: "Fixed-Move",
|
|
||||||
},
|
|
||||||
window: {
|
|
||||||
modelUrl: Window,
|
|
||||||
scale: [0.75, 0.75, 0.75],
|
|
||||||
csgscale: [5, 3, 0.5],
|
|
||||||
csgposition: [0, 1.5, 0],
|
|
||||||
type: "Free-Move",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
////////// All Toggle's //////////
|
////////// All Toggle's //////////
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -247,7 +221,6 @@ export default function Builder() {
|
|||||||
floorGroupAisle={floorGroupAisle}
|
floorGroupAisle={floorGroupAisle}
|
||||||
scene={scene}
|
scene={scene}
|
||||||
onlyFloorlines={onlyFloorlines}
|
onlyFloorlines={onlyFloorlines}
|
||||||
AssetConfigurations={AssetConfigurations}
|
|
||||||
itemsGroup={itemsGroup}
|
itemsGroup={itemsGroup}
|
||||||
isTempLoader={isTempLoader}
|
isTempLoader={isTempLoader}
|
||||||
tempLoader={tempLoader}
|
tempLoader={tempLoader}
|
||||||
@@ -260,7 +233,6 @@ export default function Builder() {
|
|||||||
|
|
||||||
<WallsAndWallItems
|
<WallsAndWallItems
|
||||||
CSGGroup={CSGGroup}
|
CSGGroup={CSGGroup}
|
||||||
AssetConfigurations={AssetConfigurations}
|
|
||||||
setSelectedItemsIndex={setSelectedItemsIndex}
|
setSelectedItemsIndex={setSelectedItemsIndex}
|
||||||
selectedItemsIndex={selectedItemsIndex}
|
selectedItemsIndex={selectedItemsIndex}
|
||||||
currentWallItem={currentWallItem}
|
currentWallItem={currentWallItem}
|
||||||
|
|||||||
@@ -27,7 +27,16 @@ export const Csg: React.FC<CsgProps> = (props) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
props.hoveredDeletableWallItem.current = hovered ? object : null;
|
let currentObject = object;
|
||||||
|
while (currentObject) {
|
||||||
|
if (currentObject.name === "Scene") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentObject = currentObject.parent as THREE.Mesh;
|
||||||
|
}
|
||||||
|
if (currentObject) {
|
||||||
|
props.hoveredDeletableWallItem.current = hovered ? currentObject : null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -35,29 +35,26 @@ function handleMeshDown(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event.intersections.length > 0) {
|
if (event.intersections.length > 0) {
|
||||||
const clickedIndex = wallItems.findIndex((item) => item.model === event.intersections[0]?.object?.parent?.parent);
|
if (event.object) {
|
||||||
if (clickedIndex !== -1) {
|
const wallItemModel = event.object;
|
||||||
setSelectedItemsIndex(clickedIndex);
|
let currentObject = wallItemModel as THREE.Object3D;
|
||||||
const wallItemModel = wallItems[clickedIndex]?.model;
|
while (currentObject) {
|
||||||
if (wallItemModel && wallItemModel.parent && wallItemModel.parent.parent) {
|
if (currentObject.name === "Scene") {
|
||||||
currentWallItem.current = (wallItemModel.parent.parent.children[0]?.children[1]?.children[0] as Types.Mesh) || null;
|
break;
|
||||||
setSelectedWallItem(wallItemModel.parent);
|
}
|
||||||
// currentWallItem.current?.children.forEach((child) => {
|
currentObject = currentObject.parent as THREE.Object3D;
|
||||||
// if ((child as THREE.Mesh).isMesh && child.name !== "CSG_REF") {
|
}
|
||||||
// const material = (child as THREE.Mesh).material;
|
if (!currentObject) return;
|
||||||
// if (Array.isArray(material)) {
|
const clickedIndex = wallItems.findIndex((item) => item.model?.uuid === currentObject.uuid);
|
||||||
// material.forEach(mat => {
|
if (clickedIndex !== -1) {
|
||||||
// if (mat instanceof THREE.MeshStandardMaterial) {
|
setSelectedItemsIndex(clickedIndex);
|
||||||
// mat.emissive = new THREE.Color("green");
|
const wallItemModel = wallItems[clickedIndex]?.model;
|
||||||
// }
|
if (wallItemModel) {
|
||||||
// });
|
setSelectedWallItem(wallItemModel);
|
||||||
// } else if (material instanceof THREE.MeshStandardMaterial) {
|
}
|
||||||
// material.emissive = new THREE.Color("green");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ async function handleModelLoad(
|
|||||||
socket.emit("v2:model-asset:add", completeData);
|
socket.emit("v2:model-asset:add", completeData);
|
||||||
|
|
||||||
gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
|
gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
|
||||||
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } });
|
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { echo.success("Model Added!"); } });
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
@@ -421,7 +421,7 @@ async function handleModelLoad(
|
|||||||
socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
|
gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
|
||||||
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } });
|
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { echo.success("Model Added!"); } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ async function DeleteFloorItems(
|
|||||||
}
|
}
|
||||||
setFloorItems(updatedItems);
|
setFloorItems(updatedItems);
|
||||||
|
|
||||||
toast.success("Model Removed!");
|
echo.success("Model Removed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ async function DeleteLayer(
|
|||||||
floorGroup.current?.remove(meshToRemove);
|
floorGroup.current?.remove(meshToRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.success("Layer Removed!");
|
echo.success("Layer Removed!");
|
||||||
setRemovedLayer(null);
|
setRemovedLayer(null);
|
||||||
}
|
}
|
||||||
export default DeleteLayer;
|
export default DeleteLayer;
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ function deleteLine(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
toast.success("Line Removed!");
|
echo.success("Line Removed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
export default deleteLine;
|
export default deleteLine;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function DeletePillar(
|
|||||||
(<any>hoveredDeletablePillar.current.material).dispose();
|
(<any>hoveredDeletablePillar.current.material).dispose();
|
||||||
(<any>hoveredDeletablePillar.current.geometry).dispose();
|
(<any>hoveredDeletablePillar.current.geometry).dispose();
|
||||||
floorGroup.current.remove(hoveredDeletablePillar.current);
|
floorGroup.current.remove(hoveredDeletablePillar.current);
|
||||||
toast.success("Pillar Removed!");
|
echo.success("Pillar Removed!");
|
||||||
hoveredDeletablePillar.current = undefined;
|
hoveredDeletablePillar.current = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ function deletePoint(
|
|||||||
|
|
||||||
RemoveConnectedLines(DeletedPointUUID, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines);
|
RemoveConnectedLines(DeletedPointUUID, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, lines);
|
||||||
|
|
||||||
toast.success("Point Removed!");
|
echo.success("Point Removed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
export default deletePoint;
|
export default deletePoint;
|
||||||
|
|||||||
@@ -1,108 +1,138 @@
|
|||||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
import * as CONSTANTS from '../../../../types/world/worldConstants';
|
import * as CONSTANTS from '../../../../types/world/worldConstants';
|
||||||
// import { setWallItem } from '../../../../services/factoryBuilder/assest/wallAsset/setWallItemApi';
|
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
|
import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils';
|
||||||
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
|
||||||
|
|
||||||
async function AddWallItems(
|
async function AddWallItems(
|
||||||
selected: Types.String,
|
selected: any,
|
||||||
raycaster: THREE.Raycaster,
|
raycaster: THREE.Raycaster,
|
||||||
CSGGroup: Types.RefMesh,
|
CSGGroup: Types.RefMesh,
|
||||||
AssetConfigurations: Types.AssetConfigurations,
|
|
||||||
setWallItems: Types.setWallItemSetState,
|
setWallItems: Types.setWallItemSetState,
|
||||||
socket: Socket<any>
|
socket: Socket<any>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|
||||||
////////// Load Wall GLtf's and set the positions, rotation, type etc. in state and store in localstorage //////////
|
|
||||||
|
|
||||||
let intersects = raycaster?.intersectObject(CSGGroup.current!, true);
|
let intersects = raycaster?.intersectObject(CSGGroup.current!, true);
|
||||||
const wallRaycastIntersection = intersects?.find((child) => child.object.name.includes("WallRaycastReference"));
|
const wallRaycastIntersection = intersects?.find((child) => child.object.name.includes("WallRaycastReference"));
|
||||||
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||||
|
|
||||||
if (wallRaycastIntersection) {
|
if (!wallRaycastIntersection) return;
|
||||||
const intersectionPoint = wallRaycastIntersection;
|
|
||||||
const loader = new GLTFLoader();
|
const intersectionPoint = wallRaycastIntersection;
|
||||||
loader.load(AssetConfigurations[selected].modelUrl, async (gltf) => {
|
const loader = new GLTFLoader();
|
||||||
const model = gltf.scene;
|
const dracoLoader = new DRACOLoader();
|
||||||
model.userData = { wall: intersectionPoint.object.parent };
|
|
||||||
model.children[0].children.forEach((child) => {
|
dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
|
||||||
if (child.name !== "CSG_REF") {
|
loader.setDRACOLoader(dracoLoader);
|
||||||
child.castShadow = true;
|
|
||||||
child.receiveShadow = true;
|
// Check THREE.js cache first
|
||||||
}
|
const cachedModel = THREE.Cache.get(selected.id);
|
||||||
|
if (cachedModel) {
|
||||||
|
handleModelLoad(cachedModel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check IndexedDB cache
|
||||||
|
const cachedModelBlob = await retrieveGLTF(selected.id);
|
||||||
|
if (cachedModelBlob) {
|
||||||
|
const blobUrl = URL.createObjectURL(cachedModelBlob);
|
||||||
|
loader.load(blobUrl, (gltf) => {
|
||||||
|
URL.revokeObjectURL(blobUrl);
|
||||||
|
THREE.Cache.remove(blobUrl);
|
||||||
|
THREE.Cache.add(selected.id, gltf);
|
||||||
|
handleModelLoad(gltf);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load from backend if not in any cache
|
||||||
|
loader.load(`${url_Backend_dwinzo}/api/v2/AssetFile/${selected.id}`, async (gltf) => {
|
||||||
|
try {
|
||||||
|
const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v2/AssetFile/${selected.id}`).then((res) => res.blob());
|
||||||
|
await storeGLTF(selected.id, modelBlob);
|
||||||
|
THREE.Cache.add(selected.id, gltf);
|
||||||
|
await handleModelLoad(gltf);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to cache model:', error);
|
||||||
|
handleModelLoad(gltf);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleModelLoad(gltf: GLTF) {
|
||||||
|
const model = gltf.scene.clone();
|
||||||
|
model.userData = { wall: intersectionPoint.object.parent };
|
||||||
|
|
||||||
|
model.children[0].children.forEach((child) => {
|
||||||
|
if (child.name !== "CSG_REF") {
|
||||||
|
child.castShadow = true;
|
||||||
|
child.receiveShadow = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const boundingBox = new THREE.Box3().setFromObject(model);
|
||||||
|
const size = new THREE.Vector3();
|
||||||
|
boundingBox.getSize(size);
|
||||||
|
|
||||||
|
const csgscale = [size.x, size.y, size.z] as [number, number, number];
|
||||||
|
|
||||||
|
const center = new THREE.Vector3();
|
||||||
|
boundingBox.getCenter(center);
|
||||||
|
const csgposition = [center.x, center.y, center.z] as [number, number, number];
|
||||||
|
|
||||||
|
let positionY = selected.subCategory === 'fixed-move' ? 0 : intersectionPoint.point.y;
|
||||||
|
if (positionY === 0) {
|
||||||
|
positionY = Math.floor(intersectionPoint.point.y / CONSTANTS.wallConfig.height) * CONSTANTS.wallConfig.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newWallItem = {
|
||||||
|
type: selected.subCategory,
|
||||||
|
model: model,
|
||||||
|
modelName: selected.name,
|
||||||
|
modelfileID: selected.id,
|
||||||
|
scale: [1, 1, 1] as [number, number, number],
|
||||||
|
csgscale: csgscale,
|
||||||
|
csgposition: csgposition,
|
||||||
|
position: [intersectionPoint.point.x, positionY, intersectionPoint.point.z] as [number, number, number],
|
||||||
|
quaternion: intersectionPoint.object.quaternion.clone() as Types.QuaternionType
|
||||||
|
};
|
||||||
|
|
||||||
|
const email = localStorage.getItem('email');
|
||||||
|
const organization = email ? (email.split("@")[1]).split(".")[0] : 'default';
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization: organization,
|
||||||
|
modelUuid: model.uuid,
|
||||||
|
modelName: newWallItem.modelName,
|
||||||
|
modelfileID: selected.id,
|
||||||
|
type: selected.subCategory,
|
||||||
|
csgposition: newWallItem.csgposition,
|
||||||
|
csgscale: newWallItem.csgscale,
|
||||||
|
position: newWallItem.position,
|
||||||
|
quaternion: newWallItem.quaternion,
|
||||||
|
scale: newWallItem.scale,
|
||||||
|
socketId: socket.id
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('v1:wallItems:set', data);
|
||||||
|
|
||||||
|
setWallItems((prevItems) => {
|
||||||
|
const updatedItems = [...prevItems, newWallItem];
|
||||||
|
|
||||||
|
const WallItemsForStorage = updatedItems.map(item => {
|
||||||
|
const { model, ...rest } = item;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
modelUuid: model?.uuid,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const config = AssetConfigurations[selected];
|
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
|
||||||
let positionY = config.type === 'Fixed-Move' ? 0 : intersectionPoint.point.y;
|
echo.success("Model Added!");
|
||||||
if (positionY === 0) {
|
return updatedItems;
|
||||||
positionY = Math.floor(intersectionPoint.point.y / CONSTANTS.wallConfig.height) * CONSTANTS.wallConfig.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newWallItem = {
|
|
||||||
type: config.type,
|
|
||||||
model: model,
|
|
||||||
modelName: selected,
|
|
||||||
scale: config.scale,
|
|
||||||
csgscale: config.csgscale,
|
|
||||||
csgposition: config.csgposition,
|
|
||||||
position: [intersectionPoint.point.x, positionY, intersectionPoint.point.z] as [number, number, number],
|
|
||||||
quaternion: intersectionPoint.object.quaternion.clone() as Types.QuaternionType
|
|
||||||
};
|
|
||||||
|
|
||||||
const email = localStorage.getItem('email')
|
|
||||||
const organization = (email!.split("@")[1]).split(".")[0];
|
|
||||||
|
|
||||||
//REST
|
|
||||||
|
|
||||||
// await setWallItem(
|
|
||||||
// organization,
|
|
||||||
// model.uuid,
|
|
||||||
// newWallItem.modelName,
|
|
||||||
// newWallItem.type!,
|
|
||||||
// newWallItem.csgposition!,
|
|
||||||
// newWallItem.csgscale!,
|
|
||||||
// newWallItem.position,
|
|
||||||
// newWallItem.quaternion,
|
|
||||||
// newWallItem.scale!,
|
|
||||||
// )
|
|
||||||
|
|
||||||
//SOCKET
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
organization: organization,
|
|
||||||
modelUuid: model.uuid,
|
|
||||||
modelName: newWallItem.modelName,
|
|
||||||
type: newWallItem.type!,
|
|
||||||
csgposition: newWallItem.csgposition!,
|
|
||||||
csgscale: newWallItem.csgscale!,
|
|
||||||
position: newWallItem.position,
|
|
||||||
quaternion: newWallItem.quaternion,
|
|
||||||
scale: newWallItem.scale!,
|
|
||||||
socketId: socket.id
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.emit('v1:wallItems:set', data);
|
|
||||||
|
|
||||||
setWallItems((prevItems) => {
|
|
||||||
const updatedItems = [...prevItems, newWallItem];
|
|
||||||
|
|
||||||
const WallItemsForStorage = updatedItems.map(item => {
|
|
||||||
const { model, ...rest } = item;
|
|
||||||
return {
|
|
||||||
...rest,
|
|
||||||
modelUuid: model?.uuid,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
|
|
||||||
toast.success("Model Added!");
|
|
||||||
|
|
||||||
return updatedItems;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AddWallItems;
|
export default AddWallItems;
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
import { toast } from 'react-toastify';
|
|
||||||
|
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
// import { deleteWallItem } from '../../../../services/factoryBuilder/assest/wallAsset/deleteWallItemApi';
|
// import { deleteWallItem } from '../../../../services/factoryBuilder/assest/wallAsset/deleteWallItemApi';
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
@@ -13,11 +11,11 @@ function DeleteWallItems(
|
|||||||
|
|
||||||
////////// Deleting the hovered Wall GLTF from thewallItems and also update it in the localstorage //////////
|
////////// Deleting the hovered Wall GLTF from thewallItems and also update it in the localstorage //////////
|
||||||
|
|
||||||
if (hoveredDeletableWallItem.current && hoveredDeletableWallItem.current.parent) {
|
if (hoveredDeletableWallItem.current && hoveredDeletableWallItem.current) {
|
||||||
setWallItems([]);
|
setWallItems([]);
|
||||||
let WallItemsRef = wallItems;
|
let WallItemsRef = wallItems;
|
||||||
const removedItem = WallItemsRef.find((item) => item.model?.uuid === hoveredDeletableWallItem.current?.parent?.uuid);
|
const removedItem = WallItemsRef.find((item) => item.model?.uuid === hoveredDeletableWallItem.current?.uuid);
|
||||||
const Items = WallItemsRef.filter((item) => item.model?.uuid !== hoveredDeletableWallItem.current?.parent?.uuid);
|
const Items = WallItemsRef.filter((item) => item.model?.uuid !== hoveredDeletableWallItem.current?.uuid);
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
WallItemsRef = Items;
|
WallItemsRef = Items;
|
||||||
@@ -50,7 +48,6 @@ function DeleteWallItems(
|
|||||||
});
|
});
|
||||||
|
|
||||||
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
|
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
|
||||||
toast.success("Model Removed!");
|
|
||||||
hoveredDeletableWallItem.current = null;
|
hoveredDeletableWallItem.current = null;
|
||||||
}, 50);
|
}, 50);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ const FloorItemsGroup = ({
|
|||||||
const onDrop = (event: any) => {
|
const onDrop = (event: any) => {
|
||||||
if (!event.dataTransfer?.files[0]) return;
|
if (!event.dataTransfer?.files[0]) return;
|
||||||
|
|
||||||
if (selectedItem.id !== "" && event.dataTransfer?.files[0]) {
|
if (selectedItem.id !== "" && event.dataTransfer?.files[0] && selectedItem.category !== 'Fenestration') {
|
||||||
addAssetModel(
|
addAssetModel(
|
||||||
raycaster,
|
raycaster,
|
||||||
state.camera,
|
state.camera,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
useSelectedWallItem,
|
useSelectedWallItem,
|
||||||
useSocketStore,
|
useSocketStore,
|
||||||
useWallItems,
|
useWallItems,
|
||||||
|
useSelectedItem,
|
||||||
} from "../../../store/store";
|
} from "../../../store/store";
|
||||||
import { Csg } from "../csg/csg";
|
import { Csg } from "../csg/csg";
|
||||||
import * as Types from "../../../types/world/worldTypes";
|
import * as Types from "../../../types/world/worldTypes";
|
||||||
@@ -21,7 +22,6 @@ import useModuleStore from "../../../store/useModuleStore";
|
|||||||
|
|
||||||
const WallItemsGroup = ({
|
const WallItemsGroup = ({
|
||||||
currentWallItem,
|
currentWallItem,
|
||||||
AssetConfigurations,
|
|
||||||
hoveredDeletableWallItem,
|
hoveredDeletableWallItem,
|
||||||
selectedItemsIndex,
|
selectedItemsIndex,
|
||||||
setSelectedItemsIndex,
|
setSelectedItemsIndex,
|
||||||
@@ -37,34 +37,22 @@ const WallItemsGroup = ({
|
|||||||
const { deletePointOrLine } = useDeletePointOrLine();
|
const { deletePointOrLine } = useDeletePointOrLine();
|
||||||
const { setSelectedWallItem } = useSelectedWallItem();
|
const { setSelectedWallItem } = useSelectedWallItem();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
|
const { selectedItem, setSelectedItem } = useSelectedItem();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Load Wall Items from the backend
|
// Load Wall Items from the backend
|
||||||
loadInitialWallItems(setWallItems, AssetConfigurations);
|
loadInitialWallItems(setWallItems);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
////////// Update the Scale value changes in thewallItems State //////////
|
|
||||||
|
|
||||||
////////// Update the Position value changes in the selected item //////////
|
////////// Update the Position value changes in the selected item //////////
|
||||||
|
|
||||||
////////// Update the Rotation value changes in the selected item //////////
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const canvasElement = state.gl.domElement;
|
const canvasElement = state.gl.domElement;
|
||||||
function handlePointerMove(e: any) {
|
function handlePointerMove(e: any) {
|
||||||
if (
|
if (selectedItemsIndex !== null && !deletePointOrLine && e.buttons === 1) {
|
||||||
selectedItemsIndex !== null &&
|
|
||||||
!deletePointOrLine &&
|
|
||||||
e.buttons === 1
|
|
||||||
) {
|
|
||||||
const Raycaster = state.raycaster;
|
const Raycaster = state.raycaster;
|
||||||
const intersects = Raycaster.intersectObjects(
|
const intersects = Raycaster.intersectObjects(CSGGroup.current?.children[0].children!, true);
|
||||||
CSGGroup.current?.children[0].children!,
|
const Object = intersects.find((child) => child.object.name.includes("WallRaycastReference"));
|
||||||
true
|
|
||||||
);
|
|
||||||
const Object = intersects.find((child) =>
|
|
||||||
child.object.name.includes("WallRaycastReference")
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Object) {
|
if (Object) {
|
||||||
(state.controls as any)!.enabled = false;
|
(state.controls as any)!.enabled = false;
|
||||||
@@ -72,14 +60,14 @@ const WallItemsGroup = ({
|
|||||||
const updatedItems = [...prevItems];
|
const updatedItems = [...prevItems];
|
||||||
let position: [number, number, number] = [0, 0, 0];
|
let position: [number, number, number] = [0, 0, 0];
|
||||||
|
|
||||||
if (updatedItems[selectedItemsIndex].type === "Fixed-Move") {
|
if (updatedItems[selectedItemsIndex].type === "fixed-move") {
|
||||||
position = [
|
position = [
|
||||||
Object!.point.x,
|
Object!.point.x,
|
||||||
Math.floor(Object!.point.y / CONSTANTS.wallConfig.height) *
|
Math.floor(Object!.point.y / CONSTANTS.wallConfig.height) *
|
||||||
CONSTANTS.wallConfig.height,
|
CONSTANTS.wallConfig.height,
|
||||||
Object!.point.z,
|
Object!.point.z,
|
||||||
];
|
];
|
||||||
} else if (updatedItems[selectedItemsIndex].type === "Free-Move") {
|
} else if (updatedItems[selectedItemsIndex].type === "free-move") {
|
||||||
position = [Object!.point.x, Object!.point.y, Object!.point.z];
|
position = [Object!.point.x, Object!.point.y, Object!.point.z];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,8 +83,7 @@ const WallItemsGroup = ({
|
|||||||
updatedItems[selectedItemsIndex] = {
|
updatedItems[selectedItemsIndex] = {
|
||||||
...updatedItems[selectedItemsIndex],
|
...updatedItems[selectedItemsIndex],
|
||||||
position: position,
|
position: position,
|
||||||
quaternion:
|
quaternion: Object!.object.quaternion.clone() as Types.QuaternionType,
|
||||||
Object!.object.quaternion.clone() as Types.QuaternionType,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return updatedItems;
|
return updatedItems;
|
||||||
@@ -128,10 +115,7 @@ const WallItemsGroup = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
currentItem = updatedItems[selectedItemsIndex];
|
currentItem = updatedItems[selectedItemsIndex];
|
||||||
localStorage.setItem(
|
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
|
||||||
"WallItems",
|
|
||||||
JSON.stringify(WallItemsForStorage)
|
|
||||||
);
|
|
||||||
return updatedItems;
|
return updatedItems;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -145,6 +129,7 @@ const WallItemsGroup = ({
|
|||||||
// organization,
|
// organization,
|
||||||
// currentItem?.model?.uuid,
|
// currentItem?.model?.uuid,
|
||||||
// currentItem.modelName,
|
// currentItem.modelName,
|
||||||
|
// currentItem.modelfileID,
|
||||||
// currentItem.type!,
|
// currentItem.type!,
|
||||||
// currentItem.csgposition!,
|
// currentItem.csgposition!,
|
||||||
// currentItem.csgscale!,
|
// currentItem.csgscale!,
|
||||||
@@ -158,6 +143,7 @@ const WallItemsGroup = ({
|
|||||||
const data = {
|
const data = {
|
||||||
organization: organization,
|
organization: organization,
|
||||||
modelUuid: currentItem.model?.uuid!,
|
modelUuid: currentItem.model?.uuid!,
|
||||||
|
modelfileID: currentItem.modelfileID,
|
||||||
modelName: currentItem.modelName!,
|
modelName: currentItem.modelName!,
|
||||||
type: currentItem.type!,
|
type: currentItem.type!,
|
||||||
csgposition: currentItem.csgposition!,
|
csgposition: currentItem.csgposition!,
|
||||||
@@ -217,21 +203,19 @@ const WallItemsGroup = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onDrop = (event: any) => {
|
const onDrop = (event: any) => {
|
||||||
if (!event.dataTransfer?.files[0]) return;
|
if (selectedItem.category !== 'Fenestration') return;
|
||||||
|
|
||||||
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
|
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||||
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||||
|
|
||||||
raycaster.setFromCamera(pointer, camera);
|
raycaster.setFromCamera(pointer, camera);
|
||||||
|
|
||||||
if (AssetConfigurations[event.dataTransfer.files[0].name.split(".")[0]]) {
|
if (selectedItem.id) {
|
||||||
const selected = event.dataTransfer.files[0].name.split(".")[0];
|
if (selectedItem.subCategory) {
|
||||||
|
|
||||||
if (AssetConfigurations[selected]?.type) {
|
|
||||||
AddWallItems(
|
AddWallItems(
|
||||||
selected,
|
selectedItem,
|
||||||
raycaster,
|
raycaster,
|
||||||
CSGGroup,
|
CSGGroup,
|
||||||
AssetConfigurations,
|
|
||||||
setWallItems,
|
setWallItems,
|
||||||
socket
|
socket
|
||||||
);
|
);
|
||||||
@@ -257,7 +241,7 @@ const WallItemsGroup = ({
|
|||||||
canvasElement.removeEventListener("drop", onDrop);
|
canvasElement.removeEventListener("drop", onDrop);
|
||||||
canvasElement.removeEventListener("dragover", onDragOver);
|
canvasElement.removeEventListener("dragover", onDragOver);
|
||||||
};
|
};
|
||||||
}, [deleteTool, wallItems]);
|
}, [deleteTool, wallItems, selectedItem, camera]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (deleteTool && activeModule === "builder") {
|
if (deleteTool && activeModule === "builder") {
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ import handleMeshDown from "../eventFunctions/handleMeshDown";
|
|||||||
import handleMeshMissed from "../eventFunctions/handleMeshMissed";
|
import handleMeshMissed from "../eventFunctions/handleMeshMissed";
|
||||||
import WallsMesh from "./wallsMesh";
|
import WallsMesh from "./wallsMesh";
|
||||||
import WallItemsGroup from "./wallItemsGroup";
|
import WallItemsGroup from "./wallItemsGroup";
|
||||||
import { useEffect } from "react";
|
|
||||||
|
|
||||||
const WallsAndWallItems = ({
|
const WallsAndWallItems = ({
|
||||||
CSGGroup,
|
CSGGroup,
|
||||||
AssetConfigurations,
|
|
||||||
setSelectedItemsIndex,
|
setSelectedItemsIndex,
|
||||||
selectedItemsIndex,
|
selectedItemsIndex,
|
||||||
currentWallItem,
|
currentWallItem,
|
||||||
@@ -63,7 +61,6 @@ const WallsAndWallItems = ({
|
|||||||
<WallsMesh lines={lines} />
|
<WallsMesh lines={lines} />
|
||||||
<WallItemsGroup
|
<WallItemsGroup
|
||||||
currentWallItem={currentWallItem}
|
currentWallItem={currentWallItem}
|
||||||
AssetConfigurations={AssetConfigurations}
|
|
||||||
hoveredDeletableWallItem={hoveredDeletableWallItem}
|
hoveredDeletableWallItem={hoveredDeletableWallItem}
|
||||||
selectedItemsIndex={selectedItemsIndex}
|
selectedItemsIndex={selectedItemsIndex}
|
||||||
setSelectedItemsIndex={setSelectedItemsIndex}
|
setSelectedItemsIndex={setSelectedItemsIndex}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as CONSTANTS from "../../../types/world/worldConstants";
|
|||||||
import { Base } from "@react-three/csg";
|
import { Base } from "@react-three/csg";
|
||||||
import { MeshDiscardMaterial } from "@react-three/drei";
|
import { MeshDiscardMaterial } from "@react-three/drei";
|
||||||
import { useUpdateScene, useWalls } from "../../../store/store";
|
import { useUpdateScene, useWalls } from "../../../store/store";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { getLines } from "../../../services/factoryBuilder/lines/getLinesApi";
|
import { getLines } from "../../../services/factoryBuilder/lines/getLinesApi";
|
||||||
import objectLinesToArray from "../geomentries/lines/lineConvertions/objectLinesToArray";
|
import objectLinesToArray from "../geomentries/lines/lineConvertions/objectLinesToArray";
|
||||||
import loadWalls from "../geomentries/walls/loadWalls";
|
import loadWalls from "../geomentries/walls/loadWalls";
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -415,7 +415,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
toast.success("Object added!");
|
echo.success("Object added!");
|
||||||
clearSelection();
|
clearSelection();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
toast.success("Object duplicated!");
|
echo.success("Object duplicated!");
|
||||||
clearSelection();
|
clearSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ function MoveControls({
|
|||||||
itemsGroupRef.current.add(obj);
|
itemsGroupRef.current.add(obj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
toast.success("Object moved!");
|
echo.success("Object moved!");
|
||||||
|
|
||||||
itemsData.current = [];
|
itemsData.current = [];
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
|||||||
itemsGroupRef.current.add(obj);
|
itemsGroupRef.current.add(obj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
toast.success("Object rotated!");
|
echo.success("Object rotated!");
|
||||||
|
|
||||||
itemsData.current = [];
|
itemsData.current = [];
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ const SelectionControls: React.FC = () => {
|
|||||||
const updatedItems = floorItems.filter((item: { modelUuid: string }) => !selectedUUIDs.includes(item.modelUuid));
|
const updatedItems = floorItems.filter((item: { modelUuid: string }) => !selectedUUIDs.includes(item.modelUuid));
|
||||||
setFloorItems(updatedItems);
|
setFloorItems(updatedItems);
|
||||||
}
|
}
|
||||||
toast.success("Selected models removed!");
|
echo.success("Selected models removed!");
|
||||||
clearSelection();
|
clearSelection();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -57,9 +57,7 @@ export default function PostProcessing() {
|
|||||||
)}
|
)}
|
||||||
{selectedWallItem && (
|
{selectedWallItem && (
|
||||||
<Outline
|
<Outline
|
||||||
selection={selectedWallItem.children[1].children[0].children.filter(
|
selection={flattenChildren(selectedWallItem.children)}
|
||||||
(child: Types.Mesh) => child.name !== "CSG_REF"
|
|
||||||
)}
|
|
||||||
selectionLayer={10}
|
selectionLayer={10}
|
||||||
width={3000}
|
width={3000}
|
||||||
blendFunction={BlendFunction.ALPHA}
|
blendFunction={BlendFunction.ALPHA}
|
||||||
|
|||||||
@@ -3,22 +3,27 @@ import { useProductStore } from '../../../store/simulation/useProductStore';
|
|||||||
import { useActionHandler } from '../actions/useActionHandler';
|
import { useActionHandler } from '../actions/useActionHandler';
|
||||||
import { usePlayButtonStore, useResetButtonStore } from '../../../store/usePlayButtonStore';
|
import { usePlayButtonStore, useResetButtonStore } from '../../../store/usePlayButtonStore';
|
||||||
import { determineExecutionOrder } from './functions/determineExecutionOrder';
|
import { determineExecutionOrder } from './functions/determineExecutionOrder';
|
||||||
|
import { useSelectedProduct } from '../../../store/simulation/useSimulationStore';
|
||||||
|
|
||||||
function Simulator() {
|
function Simulator() {
|
||||||
const { products } = useProductStore();
|
const { products, getProductById } = useProductStore();
|
||||||
const { handleAction } = useActionHandler();
|
const { handleAction } = useActionHandler();
|
||||||
|
const { selectedProduct } = useSelectedProduct();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { isReset } = useResetButtonStore();
|
const { isReset } = useResetButtonStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying || isReset) return;
|
if (!isPlaying || isReset || !selectedProduct.productId) return;
|
||||||
|
|
||||||
const executionOrder = determineExecutionOrder(products);
|
const product = getProductById(selectedProduct.productId);
|
||||||
|
if (!product) return;
|
||||||
|
|
||||||
|
const executionOrder = determineExecutionOrder([product]);
|
||||||
executionOrder.forEach(point => {
|
executionOrder.forEach(point => {
|
||||||
const action = 'actions' in point ? point.actions[0] : point.action;
|
const action = 'actions' in point ? point.actions[0] : point.action;
|
||||||
handleAction(action);
|
handleAction(action);
|
||||||
});
|
});
|
||||||
}, [products, isPlaying, isReset]);
|
}, [products, isPlaying, isReset, selectedProduct]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export const useZonePoints = create<ZonePointsState>((set) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSelectedItem = create<any>((set: any) => ({
|
export const useSelectedItem = create<any>((set: any) => ({
|
||||||
selectedItem: { name: "", id: "", type: undefined },
|
selectedItem: { name: "", id: "", type: undefined, category: '', subCatergory: '' },
|
||||||
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
17
app/src/types/world/worldTypes.d.ts
vendored
17
app/src/types/world/worldTypes.d.ts
vendored
@@ -217,27 +217,14 @@ export type FloorItems = Array<FloorItemType>;
|
|||||||
// Dispatch type for setting floor item state in React
|
// Dispatch type for setting floor item state in React
|
||||||
export type setFloorItemSetState = React.Dispatch<React.SetStateAction<FloorItems | null | undefined>>;
|
export type setFloorItemSetState = React.Dispatch<React.SetStateAction<FloorItems | null | undefined>>;
|
||||||
|
|
||||||
/** Asset Configuration for Loading and Positioning **/
|
|
||||||
|
|
||||||
// Configuration for assets, allowing model URLs, scaling, positioning, and types
|
|
||||||
interface AssetConfiguration {
|
|
||||||
modelUrl: string;
|
|
||||||
scale?: [number, number, number];
|
|
||||||
csgscale?: [number, number, number];
|
|
||||||
csgposition?: [number, number, number];
|
|
||||||
type?: "Fixed-Move" | "Free-Move";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collection of asset configurations, keyed by unique identifiers
|
|
||||||
export type AssetConfigurations = { [key: string]: AssetConfiguration; };
|
|
||||||
|
|
||||||
/** Wall Item Configuration **/
|
/** Wall Item Configuration **/
|
||||||
|
|
||||||
// Configuration for wall items, including model, scale, position, and rotation
|
// Configuration for wall items, including model, scale, position, and rotation
|
||||||
interface WallItem {
|
interface WallItem {
|
||||||
type: "Fixed-Move" | "Free-Move" | undefined;
|
type: "fixed-move" | "free-move" | undefined;
|
||||||
model?: THREE.Group;
|
model?: THREE.Group;
|
||||||
modelUuid?: string;
|
modelUuid?: string;
|
||||||
|
modelfileID: string;
|
||||||
modelName?: string;
|
modelName?: string;
|
||||||
scale?: [number, number, number];
|
scale?: [number, number, number];
|
||||||
csgscale?: [number, number, number];
|
csgscale?: [number, number, number];
|
||||||
|
|||||||
Reference in New Issue
Block a user