Dwinzo_dev/app/src/modules/builder/geomentries/walls/addWallItems.ts

142 lines
5.3 KiB
TypeScript
Raw Normal View History

import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
2025-03-25 12:04:20 +00:00
import { toast } from 'react-toastify';
import * as THREE from 'three';
import * as Types from "../../../../types/world/worldTypes";
import * as CONSTANTS from '../../../../types/world/worldConstants';
import { Socket } from 'socket.io-client';
import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
2025-03-25 12:04:20 +00:00
async function AddWallItems(
selected: any,
2025-03-25 12:04:20 +00:00
raycaster: THREE.Raycaster,
CSGGroup: Types.RefMesh,
setWallItems: Types.setWallItemSetState,
socket: Socket<any>,
projectId?: string
2025-03-25 12:04:20 +00:00
): Promise<void> {
let intersects = raycaster?.intersectObject(CSGGroup.current!, true);
const wallRaycastIntersection = intersects?.find((child) => child.object.name.includes("WallRaycastReference"));
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
2025-03-25 12:04:20 +00:00
if (!wallRaycastIntersection) return;
2025-03-25 12:04:20 +00:00
const intersectionPoint = wallRaycastIntersection;
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
2025-03-25 12:04:20 +00:00
dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
loader.setDRACOLoader(dracoLoader);
2025-03-25 12:04:20 +00:00
// Check THREE.js cache first
const cachedModel = THREE.Cache.get(selected.id);
if (cachedModel) {
handleModelLoad(cachedModel);
return;
}
2025-03-25 12:04:20 +00:00
// 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;
}
2025-03-25 12:04:20 +00:00
// 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;
}
});
2025-03-25 12:04:20 +00:00
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,
assetId: 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 userId = localStorage.getItem("userId");
const data = {
organization: organization,
modelUuid: model.uuid,
modelName: newWallItem.modelName,
assetId: selected.id,
type: selected.subCategory,
csgposition: newWallItem.csgposition,
csgscale: newWallItem.csgscale,
position: newWallItem.position,
quaternion: newWallItem.quaternion,
scale: newWallItem.scale,
socketId: socket.id,
projectId,
userId
};
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,
};
2025-03-25 12:04:20 +00:00
});
localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
echo.success("Model Added!");
return updatedItems;
2025-03-25 12:04:20 +00:00
});
}
}
export default AddWallItems;