thepipis's picture
Quiero reemplazar la lógica de localStorage por una conexión real a backend (por ejemplo, con Flask o Django REST). El objetivo es permitir que los modelos cargados (UUID, nombre, posición, color, etc.) se almacenen en una API backend y se restauren automáticamente al iniciar la aplicación. 🎯 Objetivo: - Enviar los metadatos de cada modelo al backend cuando se carga. - Consultar todos los modelos guardados al iniciar para restaurar la sesión. - Eliminar todos los modelos del backend al hacer reset. 🧩 Backend: - Ruta POST `/api/models/` para guardar modelos. - Ruta GET `/api/models/` para listar modelos guardados. - Ruta DELETE `/api/models/` para eliminar todos. 🧩 Cambios en el frontend: 1. Al final de `loadModel(file)`, justo después de `models.push(model);`, agrega: ```js fetch('/api/models/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ uuid: model.uuid, name: file.name, position: { x: model.position.x, y: model.position.y, z: model.position.z }, url: URL.createObjectURL(file) // opcional, si quieres usar ObjectURL temporal }) }); Al inicio de init(), justo antes de animate();, agrega: js Copiar Editar fetch('/api/models/') .then(res => res.json()) .then(modelsData => { modelsData.forEach(data => { const loader = new THREE.GLTFLoader(); loader.load(data.url, (gltf) => { const model = gltf.scene; model.uuid = data.uuid; model.traverse(child => { if (child.isMesh) { child.castShadow = true; child.receiveShadow = true; originalMaterials.set(child.uuid, child.material.clone()); } }); const box = new THREE.Box3().setFromObject(model); const center = box.getCenter(new THREE.Vector3()); const size = box.getSize(new THREE.Vector3()); const maxDim = Math.max(size.x, size.y, size.z); const scale = 5 / maxDim; model.scale.multiplyScalar(scale); model.position.sub(center.multiplyScalar(scale)); model.position.x = data.position.x; model.position.y = data.position.y; model.position.z = data.position.z; scene.add(model); models.push(model); const selector = document.getElementById('model-selector'); const option = document.createElement('option'); option.value = model.uuid; option.textContent = data.name; selector.appendChild(option); document.getElementById('color-tools').classList.remove('opacity-50', 'pointer-events-none'); }); }); }); En setupResetButton(), reemplaza el contenido por: js Copiar Editar document.getElementById('reset-btn').addEventListener('click', () => { models.forEach(m => scene.remove(m)); models = []; originalMaterials.clear(); paintMode = false; document.getElementById('paint-mode').textContent = 'Activar pintura'; document.getElementById('paint-mode').classList.remove('bg-blue-600'); document.getElementById('paint-mode').classList.add('bg-slate-700'); document.getElementById('color-tools').classList.add('opacity-50', 'pointer-events-none'); document.body.style.cursor = 'default'; // Borrar del backend fetch('/api/models/', { method: 'DELETE' }); // Limpiar selector const selector = document.getElementById('model-selector'); selector.innerHTML = '<option value="">Selecciona un modelo</option>'; showToast('Modelos reseteados'); }); - Follow Up Deployment
788e5e7 verified