l3d-egui 0.2.3

L3D 3D viewer - works on desktop and web (WASM) with three-d
Documentation
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>L3D 3D Viewer</title>
    <link data-trunk rel="rust" data-wasm-opt="z" data-cargo-no-default-features="true" />
    <style>
        html, body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background: #262635;
        }
        #drop-hint {
            position: fixed;
            top: 10px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0,0,0,0.7);
            color: #fff;
            padding: 8px 16px;
            border-radius: 4px;
            font-family: system-ui, sans-serif;
            font-size: 14px;
            z-index: 100;
            pointer-events: none;
        }
        #drop-overlay {
            position: fixed;
            top: 0; left: 0; right: 0; bottom: 0;
            background: rgba(233, 69, 96, 0.15);
            border: 4px dashed #e94560;
            display: none;
            align-items: center;
            justify-content: center;
            z-index: 99;
            pointer-events: none;
        }
        #drop-overlay.active { display: flex; }
        #drop-overlay span {
            background: rgba(0,0,0,0.8);
            color: #fff;
            padding: 20px 40px;
            border-radius: 8px;
            font-family: system-ui, sans-serif;
            font-size: 18px;
        }
        canvas { display: block; }
        #file-input { display: none; }
    </style>
</head>
<body>
    <canvas id="canvas" style="width:100%;height:100%"></canvas>
    <div id="drop-hint">Drop L3D file or <a href="#" id="select-link" style="color:#e94560;pointer-events:auto;cursor:pointer">click to select</a></div>
    <div id="drop-overlay"><span>Drop L3D file here</span></div>
    <input type="file" id="file-input" accept=".l3d" />

    <script>
        // Wait for trunk to load WASM
        window.addEventListener('TrunkApplicationStarted', () => {
            console.log('WASM loaded by trunk');

            const bindings = window.wasmBindings;
            const dropHint = document.getElementById('drop-hint');
            const dropOverlay = document.getElementById('drop-overlay');
            const fileInput = document.getElementById('file-input');
            const selectLink = document.getElementById('select-link');

            async function handleFile(file) {
                console.log('Loading file:', file.name, file.size, 'bytes');
                dropHint.textContent = 'Loading ' + file.name + '...';

                const data = new Uint8Array(await file.arrayBuffer());
                bindings.queue_l3d_data(data);

                dropHint.textContent = 'Loaded: ' + file.name + ' - Drop another to replace';
            }

            // File selection
            selectLink.addEventListener('click', (e) => {
                e.preventDefault();
                fileInput.click();
            });

            fileInput.addEventListener('change', (e) => {
                if (e.target.files[0]) handleFile(e.target.files[0]);
            });

            // Drag & drop
            let dragCounter = 0;

            document.body.addEventListener('dragenter', (e) => {
                e.preventDefault();
                dragCounter++;
                dropOverlay.classList.add('active');
            });

            document.body.addEventListener('dragleave', (e) => {
                e.preventDefault();
                dragCounter--;
                if (dragCounter === 0) dropOverlay.classList.remove('active');
            });

            document.body.addEventListener('dragover', (e) => {
                e.preventDefault();
            });

            document.body.addEventListener('drop', (e) => {
                e.preventDefault();
                dragCounter = 0;
                dropOverlay.classList.remove('active');

                const file = e.dataTransfer.files[0];
                if (file && file.name.toLowerCase().endsWith('.l3d')) {
                    handleFile(file);
                } else {
                    dropHint.textContent = 'Please drop an .l3d file';
                }
            });

            // Start the 3D viewer
            console.log('Starting viewer...');
            bindings.start_viewer_wasm();
        });
    </script>
</body>
</html>