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 { getWallItems } from '../../../services/factoryBuilder/assest/wallAsset/getWallItemsApi'; import { retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils'; async function loadInitialWallItems( setWallItems: Types.setWallItemSetState, ): Promise { try { const email = localStorage.getItem('email'); if (!email) { throw new Error('No email found in localStorage'); } const organization = email.split("@")[1].split(".")[0]; const items = await getWallItems(organization); let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; if (!items || items.length === 0) { localStorage.removeItem("WallItems"); return; } localStorage.setItem("WallItems", JSON.stringify(items)); 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((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((resolve) => { loader.load(modelUrl, async (gltf) => { try { // Cache the model const modelBlob = await fetch(modelUrl).then((res) => res.blob()); await storeGLTF(item.modelName!, modelBlob); THREE.Cache.add(item.modelName!, gltf); resolve(processModel(gltf, item)); } catch (error) { console.error('Failed to cache model:', error); resolve(processModel(gltf, item)); } }); }); })); setWallItems(loadedWallItems); } catch (error) { console.error('Failed to load wall items:', error); } } 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;