111 lines
3.5 KiB
TypeScript
111 lines
3.5 KiB
TypeScript
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";
|
|
import { getUserData } from "../../../functions/getUserData";
|
|
|
|
async function loadInitialWallItems(
|
|
setWallItems: Types.setWallItemSetState,
|
|
projectId?: string,
|
|
versionId?: string
|
|
): Promise<void> {
|
|
if (!projectId || !versionId) return;
|
|
try {
|
|
const { organization, email } = getUserData();
|
|
|
|
if (!email) {
|
|
throw new Error("No email found in localStorage");
|
|
}
|
|
|
|
const items = await getWallItems(organization, projectId, versionId);
|
|
|
|
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.assetId!);
|
|
if (cachedModel) {
|
|
return processModel(cachedModel, item);
|
|
}
|
|
|
|
// Check IndexedDB cache
|
|
const cachedModelBlob = await retrieveGLTF(item.assetId!);
|
|
if (cachedModelBlob) {
|
|
const blobUrl = URL.createObjectURL(cachedModelBlob);
|
|
return new Promise<Types.WallItem>((resolve) => {
|
|
loader.load(blobUrl, (gltf) => {
|
|
URL.revokeObjectURL(blobUrl);
|
|
THREE.Cache.add(item.assetId!, gltf);
|
|
resolve(processModel(gltf, item));
|
|
});
|
|
});
|
|
}
|
|
|
|
// Load from original URL if not cached
|
|
const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${item.assetId!}`;
|
|
return new Promise<Types.WallItem>((resolve) => {
|
|
loader.load(modelUrl, async (gltf) => {
|
|
try {
|
|
// Cache the model
|
|
const modelBlob = await fetch(modelUrl).then((res) => res.blob());
|
|
await storeGLTF(item.assetId!, modelBlob);
|
|
THREE.Cache.add(item.assetId!, 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,
|
|
assetId: item.assetId,
|
|
scale: item.scale,
|
|
csgscale: item.csgscale,
|
|
csgposition: item.csgposition,
|
|
position: item.position,
|
|
quaternion: item.quaternion,
|
|
};
|
|
}
|
|
|
|
export default loadInitialWallItems;
|