"use client"; import { useState, useRef, useEffect } from "react"; export default function XgridsWizard() { const [files, setFiles] = useState([]); const [status, setStatus] = useState("Waiting for upload..."); const [isProcessing, setIsProcessing] = useState(false); const workerRef = useRef(null); useEffect(() => { const worker = new Worker( new URL("./workers/converter.worker.ts", import.meta.url), ); workerRef.current = worker; worker.onmessage = (e) => { const { type, message, data } = e.data; if (type === "LOG") setStatus(message); if (type === "DONE") { setIsProcessing(false); setStatus( `Conversion Complete! Downloading ${data.files.length} files...`, ); // Loop through all generated files and trigger downloads data.files.forEach((file: { name: string; blob: Blob }) => { downloadFile(file.blob, file.name); }); } }; return () => worker.terminate(); }, []); // Helper to trigger browser downloads const downloadFile = (blob: Blob, name: string) => { const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = name; a.click(); URL.revokeObjectURL(url); }; const handleFolderUpload = (e: React.ChangeEvent) => { const uploadedFiles = Array.from(e.target.files || []); if (uploadedFiles.length > 0) { setFiles(uploadedFiles); setStatus(`Loaded ${uploadedFiles.length} files. Ready to convert.`); } }; const startConversion = async () => { if (!files.length || !workerRef.current) return; setIsProcessing(true); setStatus("Reading files into memory (this might take a moment)..."); // Find the main .lcc file to act as our entry point const lccFile = files.find((f) => f.name.endsWith(".lcc")); if (!lccFile) { setStatus("Error: Missing .lcc file in folder."); setIsProcessing(false); return; } try { // 1. Convert all File objects into an array of { name, buffer } const filesData = await Promise.all( files.map(async (f) => ({ name: f.name, buffer: await f.arrayBuffer(), })), ); // 2. Extract just the ArrayBuffers so we can "transfer" them to the worker efficiently // This prevents duplicating the 272MB data in RAM const buffersToTransfer = filesData.map((f) => f.buffer); workerRef.current.postMessage( { type: "START_CONVERSION", filesData, mainLccName: lccFile.name, fileName: lccFile.name.replace(".lcc", ""), // e.g., "Wilhelm Studios" }, buffersToTransfer, // Passes ownership to the worker to save memory ); } catch (error) { console.error(error); setStatus("Error reading files. Check console."); setIsProcessing(false); } }; return (

Xgrids Scene Wizard

Convert .lcc/.lci to SOG, LODs, and PLY meshes locally.

{"> "} {status}

); }