diff --git a/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx b/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx index bbb1268..6be22ee 100644 --- a/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx +++ b/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx @@ -1,13 +1,14 @@ import * as THREE from 'three'; import { CameraControls, Decal } from '@react-three/drei' -import { useLoader, useThree } from '@react-three/fiber'; +import { useThree } from '@react-three/fiber'; import { useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store'; import { useBuilderStore } from '../../../../store/builder/useBuilderStore'; +import { retrieveImage, storeImage } from '../../../../utils/indexDB/idbUtils'; import defaultMaterial from '../../../../assets/textures/floor/wall-tex.png'; import useModuleStore from '../../../../store/useModuleStore'; import { useSceneContext } from '../../../scene/sceneContext'; -import { useEffect, useRef } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { getUserData } from '../../../../functions/getUserData'; import { useVersionContext } from '../../version/versionContext'; import { useParams } from 'react-router-dom'; @@ -28,12 +29,108 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP const { selectedVersion } = selectedVersionStore(); const { projectId } = useParams(); const { socket } = useSocketStore(); - const material = useLoader(THREE.TextureLoader, defaultMaterial); - const { raycaster, pointer, camera, scene, gl, controls } = useThree(); const isDraggingRef = useRef(false); const dragOffsetRef = useRef(null); + const [texture, setTexture] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + const loadDefaultTexture = () => { + const textureLoader = new THREE.TextureLoader(); + textureLoader.load( + defaultMaterial, + (fallbackTex) => { + fallbackTex.name = "default-decal"; + setTexture(fallbackTex); + setIsLoading(false); + }, + undefined, + (error) => { + console.error("Error loading default decal texture:", error); + setIsLoading(false); + } + ); + }; + + const loadDecalTexture = async (decalId: string) => { + setIsLoading(true); + + try { + const cachedTexture = THREE.Cache.get(decalId); + if (cachedTexture) { + setTexture(cachedTexture); + setIsLoading(false); + return; + } + + const indexedDBTexture = await retrieveImage(decalId); + if (indexedDBTexture) { + const blobUrl = URL.createObjectURL(indexedDBTexture); + const textureLoader = new THREE.TextureLoader(); + textureLoader.load( + blobUrl, + (tex) => { + URL.revokeObjectURL(blobUrl); + tex.name = decalId; + THREE.Cache.add(decalId, tex); + setTexture(tex); + setIsLoading(false); + }, + undefined, + (error) => { + console.error(`Error loading texture from IndexedDB:`, error); + URL.revokeObjectURL(blobUrl); + loadFromBackend(decalId); + } + ); + return; + } + + loadFromBackend(decalId); + } catch (error) { + console.error("Error loading decal texture:", error); + loadDefaultTexture(); + } + }; + + const loadFromBackend = (decalId: string) => { + console.log('decalId: ', decalId); + const textureUrl = `${process.env.REACT_APP_SERVER_MARKETPLACE_URL}/api/v2/DecalFile/${decalId}`; + const textureLoader = new THREE.TextureLoader(); + + textureLoader.load( + textureUrl, + async (tex) => { + tex.name = decalId; + THREE.Cache.add(decalId, tex); + setTexture(tex); + setIsLoading(false); + + try { + const response = await fetch(textureUrl); + const blob = await response.blob(); + await storeImage(decalId, blob); + } catch (error) { + console.error("Error storing texture in IndexedDB:", error); + } + }, + undefined, + (error) => { + console.error(`Error loading texture from backend:`, error); + loadDefaultTexture(); + } + ); + }; + + useEffect(() => { + if (decal.decalId) { + loadDecalTexture(decal.decalId); + } else { + loadDefaultTexture(); + } + }, [decal.decalId]); + useEffect(() => { if (!toggleView && activeModule === 'builder') { if (toolMode !== 'cursor') { @@ -227,7 +324,7 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP }} >